home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / CMPINT.C < prev    next >
C/C++ Source or Header  |  1992-03-01  |  94KB  |  3,113 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/src/microcode/RCS/cmpint.c,v 1.44 1992/02/24 22:10:33 jinx Exp $
  4.  
  5. Copyright (c) 1989-1992 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. /*
  36.  *
  37.  * Compiled code interface.  Portable version.
  38.  * This file requires a bit of assembly language from cmpaux-md.m4
  39.  * See also the files cmpint.txt, cmpgc.h, and cmpint-md.h .
  40.  *
  41.  */
  42.  
  43. #ifdef HAS_COMPILER_SUPPORT
  44. /*
  45.  * Procedures in this file belong to the following categories:
  46.  *
  47.  * Local C procedures.  These are local procedures called only by
  48.  * other procedures in this file, and have been separated only for
  49.  * modularity reasons.  They are tagged with the C keyword `static'.
  50.  * They can return any C type.
  51.  *
  52.  * C utility procedures.  These procedures are called from C
  53.  * primitives and other subsystems and never leave the C world.  They
  54.  * constitute the compiled code data abstraction as far as other C
  55.  * parts of the Scheme "microcode" are concerned.  They are tagged
  56.  * with the noise word `C_UTILITY'.  They can return any C type.
  57.  *
  58.  * C interface entries.  These procedures are called from the
  59.  * interpreter (written in C) and ultimately enter the Scheme compiled
  60.  * code world by using the assembly language utility
  61.  * `C_to_interface'.  They are tagged with the noise word
  62.  * `C_TO_SCHEME'.  They MUST return a C long indicating what
  63.  * the interpreter should do next.
  64.  *
  65.  * Scheme interface utilities.  These procedures are called from the
  66.  * assembly language interface and return to it, and perform all the
  67.  * tasks that the compiler does not code inline.  They are referenced
  68.  * by compiled scheme code by index, and the assembly language
  69.  * interface fetches them from an array.  They are tagged with the
  70.  * noise word `SCHEME_UTILITY'.  They return a C structure (struct
  71.  * utility_result) which describes whether computation should proceed
  72.  * in the interpreter or in compiled code, and how.
  73.  *
  74.  */
  75.  
  76. /* Macro imports */
  77.  
  78. #include <stdio.h>
  79. #include "oscond.h"    /* Identify the operating system */
  80. #include "ansidecl.h"    /* Macros to support ANSI declarations */
  81. #include "dstack.h"    /* Dynamic-stack support */
  82. #include "config.h"     /* SCHEME_OBJECT type and machine dependencies */
  83. #include "types.h"      /* Needed by const.h */
  84. #include "const.h"      /* REGBLOCK_MINIMUM_LENGTH and PRIM_... codes */
  85. #include "object.h"     /* Making and destructuring Scheme objects */
  86. #include "intrpt.h"    /* Interrupt processing macros */
  87. #include "gc.h"        /* Request_GC, etc. */
  88. #include "sdata.h"    /* ENTITY_OPERATOR */
  89. #include "errors.h"     /* Error codes and Termination codes */
  90. #include "returns.h"    /* Return addresses in the interpreter */
  91. #include "fixobj.h"    /* To find the error handlers */
  92. #include "stack.h"    /* Stacks and stacklets */
  93. #include "interp.h"     /* Interpreter state and primitive destructuring */
  94. #include "default.h"    /* various definitions */
  95. #include "extern.h"    /* External decls (missing Cont_Debug, etc.) */
  96. #include "trap.h"       /* UNASSIGNED_OBJECT, TRAP_EXTENSION_TYPE */
  97. #include "prims.h"      /* LEXPR */
  98. #include "prim.h"    /* Primitive_Procedure_Table, etc. */
  99. #define IN_CMPINT_C
  100. #include "cmpgc.h"      /* Compiled code object relocation */
  101.  
  102. #ifndef FLUSH_I_CACHE_REGION
  103. #  define FLUSH_I_CACHE_REGION(addr, nwords) NOP()
  104. #endif
  105.  
  106. #ifndef PUSH_D_CACHE_REGION
  107. #  define PUSH_D_CACHE_REGION(addr, nwords) FLUSH_I_CACHE_REGION(addr, nwords)
  108. #endif
  109.  
  110. /* Make noise words invisible to the C compiler. */
  111.  
  112. #define C_UTILITY
  113. #define C_TO_SCHEME
  114. #define SCHEME_UTILITY
  115.  
  116. /* For clarity */
  117.  
  118. typedef char instruction;
  119.  
  120. #ifdef C_FUNC_PTR_IS_CLOSURE
  121. #  define REFENTRY(name) (name)
  122. #  define VARENTRY(name) instruction *name
  123. #  define EXTENTRY(name) extern instruction *name
  124. #else
  125. #  define REFENTRY(name) ((void (*)()) name)
  126. #  define VARENTRY(name) void (*name)()
  127. #  define EXTENTRY(name) extern void EXFUN (name, (void))
  128. #endif
  129.  
  130. /* Structure returned by SCHEME_UTILITYs */
  131.  
  132. struct utility_result
  133. {
  134.   VARENTRY (interface_dispatch);
  135.   union additional_info
  136.   {
  137.     long                code_to_interpreter;
  138.     instruction        *entry_point;
  139.   } extra;
  140. };
  141.  
  142. /* Some convenience macros */
  143.  
  144. #define RETURN_TO_C(code)                                               \
  145. do {                                                                    \
  146.   struct utility_result temp;                                           \
  147.                                                                         \
  148.   temp.interface_dispatch = (REFENTRY (interface_to_C));        \
  149.   temp.extra.code_to_interpreter = (code);                              \
  150.                                                                         \
  151.   return (temp);                                                        \
  152. } while (false)
  153.  
  154. #define RETURN_TO_SCHEME(ep)                                            \
  155. do {                                                                    \
  156.   struct utility_result temp;                                           \
  157.                                                                         \
  158.   temp.interface_dispatch = (REFENTRY (interface_to_scheme));        \
  159.   temp.extra.entry_point = ((instruction *) (ep));            \
  160.                                                                         \
  161.   return (temp);                                                        \
  162. } while (false)
  163.  
  164. #define RETURN_UNLESS_EXCEPTION(code, entry_point)                      \
  165. {                                                                       \
  166.   int return_code;                                                      \
  167.                                                                         \
  168.   return_code = (code);                                                 \
  169.   if (return_code == PRIM_DONE)                                         \
  170.   {                                                                     \
  171.     RETURN_TO_SCHEME (entry_point);                                     \
  172.   }                                                                     \
  173.   else                                                                  \
  174.   {                                                                     \
  175.     RETURN_TO_C (return_code);                                          \
  176.   }                                                                     \
  177. }
  178.  
  179. #define ENTRY_TO_OBJECT(entry)                        \
  180.   (MAKE_POINTER_OBJECT (TC_COMPILED_ENTRY, ((SCHEME_OBJECT *) (entry))))
  181.  
  182. #define MAKE_CC_BLOCK(block_addr)                    \
  183.   (MAKE_POINTER_OBJECT (TC_COMPILED_CODE_BLOCK, block_addr))
  184.  
  185. /* Imports from the rest of the "microcode" */
  186.  
  187. extern long
  188.   EXFUN (compiler_cache_operator, (void)),
  189.   EXFUN (compiler_cache_global_operator, (void)),
  190.   EXFUN (compiler_cache_lookup, (void)),
  191.   EXFUN (compiler_cache_assignment, (void));
  192.  
  193. /* Imports from assembly language */
  194.  
  195. extern long
  196.   EXFUN (C_to_interface, (void *));
  197.  
  198. EXTENTRY (interface_to_C);
  199. EXTENTRY (interface_to_scheme);
  200.  
  201. /* Exports to the rest of the "microcode" */
  202.  
  203. extern long
  204.   compiler_interface_version,
  205.   compiler_processor_type;
  206.  
  207. extern SCHEME_OBJECT
  208.   Registers[],
  209.   compiler_utilities,
  210.   return_to_interpreter;
  211.  
  212. extern C_UTILITY long
  213.   EXFUN (make_fake_uuo_link,
  214.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  215.   EXFUN (make_uuo_link,
  216.      (SCHEME_OBJECT value, SCHEME_OBJECT extension,
  217.       SCHEME_OBJECT block, long offset)),
  218.   EXFUN (compiled_block_closure_p, (SCHEME_OBJECT block)),
  219.   EXFUN (compiled_entry_closure_p, (SCHEME_OBJECT entry)),
  220.   EXFUN (compiled_entry_to_block_offset, (SCHEME_OBJECT entry)),
  221.   EXFUN (coerce_to_compiled,
  222.      (SCHEME_OBJECT object, long arity, SCHEME_OBJECT *location));
  223.  
  224. extern C_UTILITY SCHEME_OBJECT
  225.   EXFUN (extract_uuo_link, (SCHEME_OBJECT block, long offset)),
  226.   EXFUN (extract_variable_cache,
  227.      (SCHEME_OBJECT extension, long offset)),
  228.   EXFUN (compiled_block_debugging_info, (SCHEME_OBJECT block)),
  229.   EXFUN (compiled_block_environment, (SCHEME_OBJECT block)),
  230.   EXFUN (compiled_closure_to_entry, (SCHEME_OBJECT entry)),
  231.   * EXFUN (compiled_entry_to_block_address, (SCHEME_OBJECT entry)),
  232.   EXFUN (compiled_entry_to_block, (SCHEME_OBJECT entry));
  233.  
  234. extern C_UTILITY void
  235.   EXFUN (compiler_initialize, (long fasl_p)),
  236.   EXFUN (compiler_reset, (SCHEME_OBJECT new_block)),
  237.   EXFUN (store_variable_cache,
  238.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  239.   EXFUN (compiled_entry_type,
  240.      (SCHEME_OBJECT entry, long *buffer));
  241.  
  242. extern C_TO_SCHEME long
  243.   EXFUN (enter_compiled_expression, (void)),
  244.   EXFUN (apply_compiled_procedure, (void)),
  245.   EXFUN (return_to_compiled_code, (void)),
  246.   EXFUN (comp_link_caches_restart, (void)),
  247.   EXFUN (comp_op_lookup_trap_restart, (void)),
  248.   EXFUN (comp_interrupt_restart, (void)),
  249.   EXFUN (comp_assignment_trap_restart, (void)),
  250.   EXFUN (comp_cache_lookup_apply_restart, (void)),
  251.   EXFUN (comp_lookup_trap_restart, (void)),
  252.   EXFUN (comp_safe_lookup_trap_restart, (void)),
  253.   EXFUN (comp_unassigned_p_trap_restart, (void)),
  254.   EXFUN (comp_access_restart, (void)),
  255.   EXFUN (comp_reference_restart, (void)),
  256.   EXFUN (comp_safe_reference_restart, (void)),
  257.   EXFUN (comp_unassigned_p_restart, (void)),
  258.   EXFUN (comp_unbound_p_restart, (void)),
  259.   EXFUN (comp_assignment_restart, (void)),
  260.   EXFUN (comp_definition_restart, (void)),
  261.   EXFUN (comp_lookup_apply_restart, (void)),
  262.   EXFUN (comp_error_restart, (void));
  263.  
  264. extern SCHEME_UTILITY struct utility_result
  265.   EXFUN (comutil_return_to_interpreter, ()),
  266.   EXFUN (comutil_operator_apply_trap, ()),
  267.   EXFUN (comutil_operator_arity_trap, ()),
  268.   EXFUN (comutil_operator_entity_trap, ()),
  269.   EXFUN (comutil_operator_interpreted_trap, ()),
  270.   EXFUN (comutil_operator_lexpr_trap, ()),
  271.   EXFUN (comutil_operator_primitive_trap, ()),
  272.   EXFUN (comutil_operator_lookup_trap, ()),
  273.   EXFUN (comutil_operator_1_0_trap, ()),
  274.   EXFUN (comutil_operator_2_1_trap, ()),
  275.   EXFUN (comutil_operator_2_0_trap, ()),
  276.   EXFUN (comutil_operator_3_2_trap, ()),
  277.   EXFUN (comutil_operator_3_1_trap, ()),
  278.   EXFUN (comutil_operator_3_0_trap, ()),
  279.   EXFUN (comutil_operator_4_3_trap, ()),
  280.   EXFUN (comutil_operator_4_2_trap, ()),
  281.   EXFUN (comutil_operator_4_1_trap, ()),
  282.   EXFUN (comutil_operator_4_0_trap, ()),
  283.   EXFUN (comutil_primitive_apply, ()),
  284.   EXFUN (comutil_primitive_lexpr_apply, ()),
  285.   EXFUN (comutil_apply, ()),
  286.   EXFUN (comutil_error, ()),
  287.   EXFUN (comutil_lexpr_apply, ()),
  288.   EXFUN (comutil_link, ()),
  289.   EXFUN (comutil_interrupt_closure, ()),
  290.   EXFUN (comutil_interrupt_dlink, ()),
  291.   EXFUN (comutil_interrupt_procedure, ()),
  292.   EXFUN (comutil_interrupt_continuation, ()),
  293.   EXFUN (comutil_interrupt_ic_procedure, ()),
  294.   EXFUN (comutil_assignment_trap, ()),
  295.   EXFUN (comutil_cache_lookup_apply, ()),
  296.   EXFUN (comutil_lookup_trap, ()),
  297.   EXFUN (comutil_safe_lookup_trap, ()),
  298.   EXFUN (comutil_unassigned_p_trap, ()),
  299.   EXFUN (comutil_decrement, ()),
  300.   EXFUN (comutil_divide, ()),
  301.   EXFUN (comutil_equal, ()),
  302.   EXFUN (comutil_greater, ()),
  303.   EXFUN (comutil_increment, ()),
  304.   EXFUN (comutil_less, ()),
  305.   EXFUN (comutil_minus, ()),
  306.   EXFUN (comutil_modulo, ()),
  307.   EXFUN (comutil_multiply, ()),
  308.   EXFUN (comutil_negative, ()),
  309.   EXFUN (comutil_plus, ()),
  310.   EXFUN (comutil_positive, ()),
  311.   EXFUN (comutil_quotient, ()),
  312.   EXFUN (comutil_remainder, ()),
  313.   EXFUN (comutil_zero, ()),
  314.   EXFUN (comutil_access, ()),
  315.   EXFUN (comutil_reference, ()),
  316.   EXFUN (comutil_safe_reference, ()),
  317.   EXFUN (comutil_unassigned_p, ()),
  318.   EXFUN (comutil_unbound_p, ()),
  319.   EXFUN (comutil_assignment, ()),
  320.   EXFUN (comutil_definition, ()),
  321.   EXFUN (comutil_lookup_apply, ()),
  322.   EXFUN (comutil_primitive_error, ());
  323.  
  324. extern struct utility_result
  325.   (*(utility_table[]))();
  326.  
  327. /*
  328.   Utility table used by the assembly language interface to invoke
  329.   the SCHEME_UTILITY procedures that appear in this file.
  330.  
  331.   Important: Do NOT reorder this table without changing the indices
  332.   defined on the following page and the corresponding table in the
  333.   compiler.
  334.  */
  335.  
  336. struct utility_result
  337.   (*(utility_table[]))() =
  338. {
  339.   comutil_return_to_interpreter,        /* 0x0 */
  340.   comutil_operator_apply_trap,            /* 0x1 */
  341.   comutil_operator_arity_trap,            /* 0x2 */
  342.   comutil_operator_entity_trap,            /* 0x3 */
  343.   comutil_operator_interpreted_trap,        /* 0x4 */
  344.   comutil_operator_lexpr_trap,            /* 0x5 */
  345.   comutil_operator_primitive_trap,        /* 0x6 */
  346.   comutil_operator_lookup_trap,            /* 0x7 */
  347.   comutil_operator_1_0_trap,            /* 0x8 */
  348.   comutil_operator_2_1_trap,            /* 0x9 */
  349.   comutil_operator_2_0_trap,            /* 0xa */
  350.   comutil_operator_3_2_trap,            /* 0xb */
  351.   comutil_operator_3_1_trap,            /* 0xc */
  352.   comutil_operator_3_0_trap,            /* 0xd */
  353.   comutil_operator_4_3_trap,            /* 0xe */
  354.   comutil_operator_4_2_trap,            /* 0xf */
  355.   comutil_operator_4_1_trap,            /* 0x10 */
  356.   comutil_operator_4_0_trap,            /* 0x11 */
  357.   comutil_primitive_apply,            /* 0x12 */
  358.   comutil_primitive_lexpr_apply,        /* 0x13 */
  359.   comutil_apply,                /* 0x14 */
  360.   comutil_error,                /* 0x15 */
  361.   comutil_lexpr_apply,                /* 0x16 */
  362.   comutil_link,                    /* 0x17 */
  363.   comutil_interrupt_closure,            /* 0x18 */
  364.   comutil_interrupt_dlink,            /* 0x19 */
  365.   comutil_interrupt_procedure,            /* 0x1a */
  366.   comutil_interrupt_continuation,        /* 0x1b */
  367.   comutil_interrupt_ic_procedure,        /* 0x1c */
  368.   comutil_assignment_trap,            /* 0x1d */
  369.   comutil_cache_lookup_apply,            /* 0x1e */
  370.   comutil_lookup_trap,                /* 0x1f */
  371.   comutil_safe_lookup_trap,            /* 0x20 */
  372.   comutil_unassigned_p_trap,            /* 0x21 */
  373.   comutil_decrement,                /* 0x22 */
  374.   comutil_divide,                /* 0x23 */
  375.   comutil_equal,                /* 0x24 */
  376.   comutil_greater,                /* 0x25 */
  377.   comutil_increment,                /* 0x26 */
  378.   comutil_less,                    /* 0x27 */
  379.   comutil_minus,                /* 0x28 */
  380.   comutil_multiply,                /* 0x29 */
  381.   comutil_negative,                /* 0x2a */
  382.   comutil_plus,                    /* 0x2b */
  383.   comutil_positive,                /* 0x2c */
  384.   comutil_zero,                    /* 0x2d */
  385.   comutil_access,                /* 0x2e */
  386.   comutil_reference,                /* 0x2f */
  387.   comutil_safe_reference,            /* 0x30 */
  388.   comutil_unassigned_p,                /* 0x31 */
  389.   comutil_unbound_p,                /* 0x32 */
  390.   comutil_assignment,                /* 0x33 */
  391.   comutil_definition,                /* 0x34 */
  392.   comutil_lookup_apply,                /* 0x35 */
  393.   comutil_primitive_error,            /* 0x36 */
  394.   comutil_quotient,                /* 0x37 */
  395.   comutil_remainder,                /* 0x38 */
  396.   comutil_modulo                /* 0x39 */
  397.   };
  398.  
  399. /* These definitions reflect the indices into the table above. */
  400.  
  401. #define TRAMPOLINE_K_RETURN            0x0
  402. #define TRAMPOLINE_K_APPLY            0x1
  403. #define TRAMPOLINE_K_ARITY            0x2
  404. #define TRAMPOLINE_K_ENTITY            0x3
  405. #define TRAMPOLINE_K_INTERPRETED        0x4
  406. #define TRAMPOLINE_K_LEXPR_PRIMITIVE        0x5
  407. #define TRAMPOLINE_K_PRIMITIVE            0x6
  408. #define TRAMPOLINE_K_LOOKUP            0x7
  409. #define TRAMPOLINE_K_1_0            0x8
  410. #define TRAMPOLINE_K_2_1            0x9
  411. #define TRAMPOLINE_K_2_0            0xa
  412. #define TRAMPOLINE_K_3_2            0xb
  413. #define TRAMPOLINE_K_3_1            0xc
  414. #define TRAMPOLINE_K_3_0            0xd
  415. #define TRAMPOLINE_K_4_3            0xe
  416. #define TRAMPOLINE_K_4_2            0xf
  417. #define TRAMPOLINE_K_4_1            0x10
  418. #define TRAMPOLINE_K_4_0            0x11
  419.  
  420. #define TRAMPOLINE_K_OTHER            TRAMPOLINE_K_INTERPRETED
  421.  
  422. /* Main compiled code entry points.
  423.    These are the primary entry points that the interpreter
  424.    uses to execute compiled code.
  425.    The other entry points are special purpose return
  426.    points to compiled code invoked after the interpreter has been
  427.    employed to take corrective action (interrupt, error, etc).
  428.    They are coded adjacent to the place where the interpreter
  429.    is invoked.
  430.  */
  431.  
  432. C_TO_SCHEME long
  433. DEFUN_VOID (enter_compiled_expression)
  434. {
  435.   instruction *compiled_entry_address;
  436.   SCHEME_OBJECT *block_address, environment;
  437.   unsigned long length;
  438.  
  439.   compiled_entry_address =
  440.     ((instruction *) (OBJECT_ADDRESS (Fetch_Expression ())));
  441.   if ((COMPILED_ENTRY_FORMAT_WORD (compiled_entry_address)) !=
  442.       (FORMAT_WORD_EXPR))
  443.   {
  444.     /* It self evaluates. */
  445.     Val = (Fetch_Expression ());
  446.     return (C_to_interface ((instruction *) (OBJECT_ADDRESS (STACK_POP ()))));
  447.   }
  448.  
  449. #ifdef SPLIT_CACHES
  450.   /* This is a kludge to handle the first execution. */
  451.  
  452.   Get_Compiled_Block (block_address,
  453.               ((SCHEME_OBJECT *) compiled_entry_address));
  454.   length = (OBJECT_DATUM (*block_address));
  455.   environment = (block_address [length]);
  456.   if (!(ENVIRONMENT_P (environment)))
  457.   {
  458.     /* We could actually flush just the non-marked section.
  459.        The uuo-section will be flushed when linked.
  460.      */
  461.  
  462.     PUSH_D_CACHE_REGION (block_address, (length + 1));
  463.   }
  464. #endif /* SPLIT_CACHES */
  465.  
  466.   return (C_to_interface (compiled_entry_address));
  467. }
  468.  
  469. C_TO_SCHEME long
  470. DEFUN_VOID (apply_compiled_procedure)
  471. {
  472.   static long setup_compiled_invocation();
  473.   SCHEME_OBJECT nactuals, procedure;
  474.   instruction *procedure_entry;
  475.   long result;
  476.  
  477.   nactuals = (STACK_POP ());
  478.   procedure = (STACK_POP ());
  479.   procedure_entry = ((instruction *) (OBJECT_ADDRESS (procedure)));
  480.   result = setup_compiled_invocation ((OBJECT_DATUM (nactuals)),
  481.                                       procedure_entry);
  482.   if (result == PRIM_DONE)
  483.   {
  484.     /* Go into compiled code. */
  485.     return (C_to_interface (procedure_entry));
  486.   }
  487.   else
  488.   {
  489.     return (result);
  490.   }
  491. }
  492.  
  493. /* Note that this does not check that compiled_entry_address
  494.    is a valid return address. -- Should it?
  495.  */
  496.  
  497. C_TO_SCHEME long
  498. DEFUN_VOID (return_to_compiled_code)
  499. {
  500.   instruction *compiled_entry_address;
  501.  
  502.   compiled_entry_address =
  503.     ((instruction *) (OBJECT_ADDRESS (STACK_POP ())));
  504.   return (C_to_interface (compiled_entry_address));
  505. }
  506.  
  507. /* NOTE: In the rest of this file, number of arguments (or minimum
  508.    number of arguments, etc.) is always 1 greater than the number of
  509.    arguments (it includes the procedure object).
  510.  */
  511.  
  512. static long
  513. DEFUN (setup_compiled_invocation,
  514.        (nactuals, compiled_entry_address),
  515.        long nactuals AND
  516.        instruction *compiled_entry_address)
  517. {
  518.   static long setup_lexpr_invocation();
  519.   static SCHEME_OBJECT *open_gap();
  520.   long nmin, nmax, delta;               /* all +1 */
  521.  
  522.   nmax = (COMPILED_ENTRY_MAXIMUM_ARITY (compiled_entry_address));
  523.   if (nactuals == nmax)
  524.   {
  525.     /* Either the procedure takes exactly the number of arguments
  526.        given, or it has optional arguments, no rest argument, and
  527.        all the optional arguments have been provided.  Thus the
  528.        frame is in the right format and we are done.
  529.      */
  530.     return (PRIM_DONE);
  531.   }
  532.   nmin = (COMPILED_ENTRY_MINIMUM_ARITY (compiled_entry_address));
  533.   if (nmin < 0)
  534.   {
  535.     /* Not a procedure. */
  536.     STACK_PUSH (ENTRY_TO_OBJECT (compiled_entry_address));
  537.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  538.     return (ERR_INAPPLICABLE_OBJECT);
  539.   }
  540.   if (nactuals < nmin)
  541.   {
  542.     /* Too few arguments. */
  543.     STACK_PUSH (ENTRY_TO_OBJECT (compiled_entry_address));
  544.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  545.     return (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  546.   }
  547.   delta = (nactuals - nmax);
  548.   if (delta <= 0)
  549.   {
  550.     /* The procedure takes optional arguments but no rest argument
  551.        and not all the optional arguments have been provided.
  552.        They must be defaulted.
  553.      */
  554.     ((void) (open_gap (nactuals, delta)));
  555.     return (PRIM_DONE);
  556.   }
  557.   if (nmax > 0)
  558.   {
  559.     /* Too many arguments */
  560.     STACK_PUSH (ENTRY_TO_OBJECT (compiled_entry_address));
  561.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  562.     return (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  563.   }
  564.   /* The procedure can take arbitrarily many arguments, ie.
  565.      it is a lexpr.
  566.    */
  567.   return (setup_lexpr_invocation (nactuals, nmax, compiled_entry_address));
  568. }
  569.  
  570. /* Default some optional parameters, and return the location
  571.    of the return address (one past the last actual argument location).
  572.  */
  573.  
  574. static SCHEME_OBJECT *
  575. DEFUN (open_gap,
  576.        (nactuals, delta),
  577.        register long nactuals AND register long delta)
  578. {
  579.   register SCHEME_OBJECT *gap_location, *source_location;
  580.  
  581.   /* Need to fill in optionals */
  582.  
  583.   gap_location = STACK_LOC (delta);
  584.   source_location = STACK_LOC (0);
  585.   Stack_Pointer = gap_location;
  586.   while ((--nactuals) > 0)
  587.   {
  588.     STACK_LOCATIVE_POP (gap_location) = STACK_LOCATIVE_POP (source_location);
  589.   }
  590.   delta = (- delta);
  591.   while ((--delta) >= 0)
  592.   {
  593.     STACK_LOCATIVE_POP (gap_location) = UNASSIGNED_OBJECT;
  594.   }
  595.   return (source_location);
  596. }
  597.  
  598. /* Setup a rest argument as appropriate. */
  599.  
  600. static long
  601. DEFUN (setup_lexpr_invocation,
  602.        (nactuals, nmax, entry_address),
  603.        register long nactuals AND register long nmax AND
  604.        instruction *entry_address)
  605. {
  606.   register long delta;
  607.  
  608.   /* nmax is negative! */
  609.  
  610.   delta = (nactuals + nmax);
  611.  
  612.   if (delta < 0)
  613.   {
  614.     /* Not enough arguments have been passed to allocate a list.
  615.        The missing optional arguments must be defaulted, and the
  616.        rest parameter needs to be set to the empty list.
  617.      */
  618.  
  619.     SCHEME_OBJECT *last_loc;
  620.  
  621.     last_loc = open_gap (nactuals, delta);
  622.     (STACK_LOCATIVE_PUSH (last_loc)) = EMPTY_LIST;
  623.     return (PRIM_DONE);
  624.   }
  625.   else if (delta == 0)
  626.   {
  627.     /* The number of arguments passed matches exactly the number of
  628.        formal paramters.  The last argument needs to be replaced by
  629.        a list containing it, but there is no need to pop anything
  630.        since the frame has the right size.
  631.        This does not check for gc!
  632.        The procedure should (and currently will) on entry.
  633.      */
  634.  
  635.     register SCHEME_OBJECT temp, *gap_location, *local_free;
  636.  
  637.     local_free = Free;
  638.     Free += 2;
  639.     gap_location = STACK_LOC (nactuals - 2);
  640.     temp = *gap_location;
  641.     *gap_location = (MAKE_POINTER_OBJECT (TC_LIST, local_free));
  642.     *local_free++ = temp;
  643.     *local_free = EMPTY_LIST;
  644.     return (PRIM_DONE);
  645.   }
  646.   else /* (delta > 0) */
  647.   {
  648.     /* The number of arguments passed is greater than the number of
  649.        formal parameters named by the procedure.  Excess arguments
  650.        need to be placed in a list passed at the last parameter
  651.        location. The extra arguments must then be popped from the stack.
  652.      */
  653.     long list_size;
  654.     register SCHEME_OBJECT *gap_location, *source_location;
  655.  
  656.     /* Allocate the list, and GC if necessary. */
  657.  
  658.     list_size = (2 * (delta + 1));
  659.     if (GC_Check (list_size))
  660.     {
  661.       Request_GC (list_size);
  662.       STACK_PUSH (ENTRY_TO_OBJECT (entry_address));
  663.       STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  664.       return (PRIM_APPLY_INTERRUPT);
  665.     }
  666.     gap_location = &Free[list_size];
  667.     Free = gap_location;
  668.  
  669.     /* Place the arguments in the list, and link it. */
  670.  
  671.     source_location = (STACK_LOC (nactuals - 1));
  672.     (*(--gap_location)) = EMPTY_LIST;
  673.  
  674.     while ((--delta) >= 0)
  675.     {
  676.       gap_location -= 2;
  677.       (*(gap_location + 1)) = (STACK_LOCATIVE_PUSH (source_location));
  678.       (*(gap_location)) = (MAKE_POINTER_OBJECT (TC_LIST, (gap_location + 1)));
  679.     }
  680.  
  681.     (*(--gap_location)) = (STACK_LOCATIVE_PUSH (source_location));
  682.  
  683.     /* Place the list at the appropriate location in the stack. */
  684.  
  685.     STACK_LOCATIVE_REFERENCE (source_location, 0) =
  686.       (MAKE_POINTER_OBJECT (TC_LIST, (gap_location)));
  687.  
  688.     /* Now move the arguments into their correct location in the stack
  689.        popping any unneeded locations.
  690.      */
  691.  
  692.     gap_location = (STACK_LOC (nactuals - 1));
  693.     STACK_LOCATIVE_INCREMENT (source_location);
  694.  
  695.     /* Remember that nmax is originally negative! */
  696.  
  697.     for (nmax = ((-nmax) - 1); ((--nmax) >= 0); )
  698.     {
  699.       (STACK_LOCATIVE_PUSH (gap_location)) =
  700.         (STACK_LOCATIVE_PUSH (source_location));
  701.     }
  702.     Stack_Pointer = gap_location;
  703.     return (PRIM_DONE);
  704.   }
  705. }
  706.  
  707. /*
  708.   SCHEME_UTILITYs
  709.  
  710.   Here's a mass of procedures that are called (via scheme_to_interface,
  711.   an assembly language hook) by compiled code to do various jobs.
  712.  */
  713.  
  714. /*
  715.   This is how compiled Scheme code normally returns back to the
  716.   Scheme interpreter.
  717.   It is invoked by a trampoline, which passes the address of the
  718.   trampoline storage block (empty) to it.
  719.  */
  720.  
  721. SCHEME_UTILITY struct utility_result
  722. DEFUN (comutil_return_to_interpreter,
  723.        (tramp_data, ignore_2, ignore_3, ignore_4),
  724.        SCHEME_OBJECT *tramp_data AND
  725.        long ignore_2 AND long ignore_3 AND long ignore_4)
  726. {
  727.   RETURN_TO_C (PRIM_DONE);
  728. }
  729.  
  730. /*
  731.   comutil_primitive_apply is used to invoked a C primitive.
  732.   Note that some C primitives (the so called interpreter hooks)
  733.   will not return normally, but will "longjmp" to the interpreter
  734.   instead.  Thus the assembly language invoking this should have
  735.   set up the appropriate locations in case this happens.
  736.   After invoking the primitive, it pops the arguments off the
  737.   Scheme stack, and proceeds by invoking the continuation on top
  738.   of the stack.
  739.  */
  740.  
  741. SCHEME_UTILITY struct utility_result
  742. DEFUN (comutil_primitive_apply,
  743.        (primitive, ignore_2, ignore_3, ignore_4),
  744.        SCHEME_OBJECT primitive AND
  745.        long ignore_2 AND long ignore_3 AND long ignore_4)
  746.   PRIMITIVE_APPLY (Val, primitive);
  747.   POP_PRIMITIVE_FRAME (PRIMITIVE_ARITY (primitive));
  748.   RETURN_TO_SCHEME (OBJECT_ADDRESS (STACK_POP ()));
  749. }
  750.  
  751. /*
  752.   comutil_primitive_lexpr_apply is like comutil_primitive_apply
  753.   except that it is used to invoke primitives that take
  754.   an arbitrary number of arguments.
  755.   The number of arguments is in the REGBLOCK_LEXPR_ACTUALS slot
  756.   of the register block.
  757.  */
  758.  
  759. SCHEME_UTILITY struct utility_result
  760. DEFUN (comutil_primitive_lexpr_apply,
  761.        (primitive, ignore_2, ignore_3, ignore_4),
  762.        SCHEME_OBJECT primitive AND
  763.        long ignore_2 AND long ignore_3 AND long ignore_4)
  764. {
  765.   PRIMITIVE_APPLY (Val, primitive);
  766.   POP_PRIMITIVE_FRAME (((long) Regs[REGBLOCK_LEXPR_ACTUALS]));
  767.   RETURN_TO_SCHEME (OBJECT_ADDRESS (STACK_POP ()));
  768. }
  769.  
  770. /*
  771.   comutil_apply is used by compiled code to invoke an unknown
  772.   procedure.  It dispatches on its type to the correct place.  It
  773.   expects the procedure to invoke, and the number of arguments (+ 1).
  774.  */
  775.  
  776. SCHEME_UTILITY struct utility_result
  777. DEFUN (comutil_apply,
  778.        (procedure, nactuals, ignore_3, ignore_4),
  779.        SCHEME_OBJECT procedure AND
  780.        long nactuals AND long ignore_3 AND long ignore_4)
  781. {
  782.   switch (OBJECT_TYPE (procedure))
  783.   {
  784.     case TC_COMPILED_ENTRY:
  785.     callee_is_compiled:
  786.     {
  787.       instruction *entry_point;
  788.  
  789.       entry_point = ((instruction *) (OBJECT_ADDRESS (procedure)));
  790.       RETURN_UNLESS_EXCEPTION
  791.         ((setup_compiled_invocation (nactuals, entry_point)),
  792.          entry_point);
  793.     }
  794.  
  795.     case TC_ENTITY:
  796.     {
  797.       SCHEME_OBJECT operator;
  798.  
  799.       operator = (MEMORY_REF (procedure, ENTITY_OPERATOR));
  800.       if (!(COMPILED_CODE_ADDRESS_P (operator)))
  801.       {
  802.         goto callee_is_interpreted;
  803.       }
  804.       STACK_PUSH (procedure);           /* The entity itself */
  805.       procedure = operator;
  806.       nactuals += 1;
  807.       goto callee_is_compiled;
  808.     }
  809.     case TC_PRIMITIVE:
  810.     {
  811.       /* This code depends on the fact that unimplemented
  812.          primitives map into a "fake" primitive which accepts
  813.          any number of arguments, thus the arity test will
  814.          fail for unimplemented primitives.
  815.        */
  816.  
  817.       long arity;
  818.  
  819.       arity = (PRIMITIVE_ARITY (procedure));
  820.       if (arity == (nactuals - 1))
  821.       {
  822.         return (comutil_primitive_apply (procedure, 0, 0, 0));
  823.       }
  824.  
  825.       if (arity != LEXPR)
  826.       {
  827.         /* Wrong number of arguments. */
  828.         STACK_PUSH (procedure);
  829.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  830.         RETURN_TO_C (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  831.       }
  832.       if (!(IMPLEMENTED_PRIMITIVE_P (procedure)))
  833.       {
  834.         /* Let the interpreter handle it. */
  835.         goto callee_is_interpreted;
  836.       }
  837.       /* "Lexpr" primitive. */
  838.       Regs[REGBLOCK_LEXPR_ACTUALS] = ((SCHEME_OBJECT) (nactuals - 1));
  839.       return (comutil_primitive_lexpr_apply (procedure, 0, 0, 0));
  840.     }
  841.  
  842.     callee_is_interpreted:
  843.     default:
  844.     {
  845.       STACK_PUSH (procedure);
  846.       STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  847.       RETURN_TO_C (PRIM_APPLY);
  848.     }
  849.   }
  850. }
  851.  
  852. /*
  853.   comutil_error is used by compiled code to signal an error.  It
  854.   expects the arguments to the error procedure to be pushed on the
  855.   stack, and is passed the number of arguments (+ 1).
  856. */
  857.  
  858. SCHEME_UTILITY struct utility_result
  859. DEFUN (comutil_error,
  860.        (nactuals, ignore_2, ignore_3, ignore_4),
  861.        long nactuals AND long ignore_2 AND long ignore_3 AND long ignore_4)
  862. {
  863.   SCHEME_OBJECT error_procedure;
  864.  
  865.   error_procedure = (Get_Fixed_Obj_Slot (Compiler_Err_Procedure));
  866.   return (comutil_apply (error_procedure, nactuals, 0, 0));
  867. }
  868.  
  869. /*
  870.   comutil_lexpr_apply is invoked to reformat the frame when compiled
  871.   code calls a known lexpr.  The actual arguments are on the stack,
  872.   and it is given the number of arguments (WITHOUT counting the entry
  873.   point being invoked), and the real entry point of the procedure.
  874.  
  875.   Important: This code assumes that it is always invoked with a valid
  876.   number of arguments (the compiler checked it), and will not check.
  877.  */
  878.  
  879. SCHEME_UTILITY struct utility_result
  880. DEFUN (comutil_lexpr_apply,
  881.        (entry_address, nactuals, ignore_3, ignore_4),
  882.        register instruction *entry_address AND
  883.        long nactuals AND
  884.        long ignore_3 AND long ignore_4)
  885. {
  886.   RETURN_UNLESS_EXCEPTION
  887.     ((setup_lexpr_invocation
  888.       ((nactuals + 1),
  889.        (COMPILED_ENTRY_MAXIMUM_ARITY (entry_address)),
  890.        entry_address)),
  891.      entry_address);
  892. }
  893.  
  894. /* Core of comutil_link and comp_link_caches_restart. */
  895.  
  896. static Boolean linking_cc_block_p = false;
  897.  
  898. static void
  899. DEFUN (abort_link_cc_block, (ap), PTR ap)
  900. {
  901.   linking_cc_block_p = (* ((Boolean *) (ap)));
  902.   return;
  903. }
  904.  
  905. static long
  906. DEFUN (link_cc_block,
  907.        (block_address, offset, last_header_offset,
  908.     sections, original_count, ret_add),
  909.        register SCHEME_OBJECT *block_address AND
  910.        register long offset AND
  911.        long last_header_offset AND
  912.        long sections AND
  913.        long original_count AND
  914.        instruction *ret_add)
  915. {
  916.   Boolean execute_p;
  917.   register long entry_size, count;
  918.   SCHEME_OBJECT block;
  919.   SCHEME_OBJECT header;
  920.   long result, kind, total_count;
  921.   long (*cache_handler)();
  922.  
  923.   transaction_begin ();
  924.   {
  925.     Boolean * ap = (dstack_alloc (sizeof (Boolean)));
  926.     *ap = linking_cc_block_p;
  927.     transaction_record_action (tat_abort, abort_link_cc_block, ap);
  928.   }
  929.   linking_cc_block_p = true;
  930.  
  931.   result = PRIM_DONE;
  932.   block = (MAKE_CC_BLOCK (block_address));
  933.  
  934.   while ((--sections) >= 0)
  935.   {
  936.     SCHEME_OBJECT * scan = &(block_address[last_header_offset]);
  937.     header = (*scan);
  938.  
  939.     kind = (READ_LINKAGE_KIND (header));
  940.     switch (kind)
  941.     {
  942.       case OPERATOR_LINKAGE_KIND:
  943.     cache_handler = compiler_cache_operator;
  944.  
  945.       handle_operator:
  946.         execute_p = true;
  947.     entry_size = EXECUTE_CACHE_ENTRY_SIZE;
  948.     START_OPERATOR_RELOCATION (scan);
  949.     count = (READ_OPERATOR_LINKAGE_COUNT (header));
  950.     break;
  951.  
  952.       case GLOBAL_OPERATOR_LINKAGE_KIND:
  953.     cache_handler = compiler_cache_global_operator;
  954.     goto handle_operator;
  955.  
  956.       case REFERENCE_LINKAGE_KIND:
  957.     cache_handler = compiler_cache_lookup;
  958.       handle_reference:
  959.     execute_p = false;
  960.     entry_size = 1;
  961.     count = (READ_CACHE_LINKAGE_COUNT (header));
  962.     break;
  963.  
  964.       case ASSIGNMENT_LINKAGE_KIND:
  965.     cache_handler = compiler_cache_assignment;
  966.     goto handle_reference;
  967.  
  968.       default:
  969.     offset += 1;
  970.     total_count = (READ_CACHE_LINKAGE_COUNT (header));
  971.     count = (total_count - 1);
  972.     result = ERR_COMPILED_CODE_ERROR;
  973.     goto back_out;
  974.     }
  975.  
  976.     /* This accomodates the re-entry case after a GC.
  977.        It undoes the effects of the "smash header" code below.
  978.      */
  979.  
  980.     if ((OBJECT_TYPE (header)) == TC_LINKAGE_SECTION)
  981.     {
  982.       count = (original_count - count);
  983.       total_count = original_count;
  984.     }
  985.     else
  986.     {
  987.       total_count = count;
  988.       if (execute_p)
  989.     offset += (FIRST_OPERATOR_LINKAGE_OFFSET - 1);
  990.     }
  991.  
  992.     block_address[last_header_offset] =
  993.       (MAKE_LINKAGE_SECTION_HEADER (kind, total_count));
  994.     for (offset += 1; ((--count) >= 0); offset += entry_size)
  995.     {
  996.       SCHEME_OBJECT name;
  997.  
  998.       if (!execute_p)
  999.     name = (block_address[offset]);
  1000.       else
  1001.     EXTRACT_EXECUTE_CACHE_SYMBOL(name, &(block_address[offset]));
  1002.  
  1003.       result = ((*cache_handler)(name, block, offset));
  1004.       if (result != PRIM_DONE)
  1005.       {
  1006.         /* Save enough state to continue.
  1007.        Note that offset is decremented to compensate for it being
  1008.        incremented by the for loop header.
  1009.        Similary sections and count are incremented to compensate
  1010.        for loop headers pre-decrementing.
  1011.        count is saved although it's not needed for re-entry to
  1012.        match the assembly language versions.
  1013.      */
  1014.  
  1015.   back_out:
  1016.     if (execute_p)
  1017.       END_OPERATOR_RELOCATION (&(block_address[offset]));
  1018.         STACK_PUSH (ENTRY_TO_OBJECT (ret_add));
  1019.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (sections + 1));
  1020.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (last_header_offset));
  1021.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (offset - 1));
  1022.         STACK_PUSH (block);
  1023.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (count + 1));
  1024.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (total_count));
  1025.  
  1026.         Store_Expression (SHARP_F);
  1027.         Store_Return (RC_COMP_LINK_CACHES_RESTART);
  1028.         Save_Cont ();
  1029.  
  1030.         /* Smash header for the garbage collector.
  1031.            It is smashed back on return.  See the comment above.
  1032.          */
  1033.  
  1034.         block_address[last_header_offset] =
  1035.           (MAKE_LINKAGE_SECTION_HEADER (kind, (total_count - (count + 1))));
  1036.     goto exit_proc;
  1037.       }
  1038.     }
  1039.     if (execute_p)
  1040.       END_OPERATOR_RELOCATION (&(block_address[offset - 1]));
  1041.     last_header_offset = offset;
  1042.   }
  1043.  
  1044. exit_proc:
  1045.   /* Rather than commit, since we want to undo */
  1046.   transaction_abort ();
  1047.   PUSH_D_CACHE_REGION (block_address,
  1048.                (((unsigned long) (*block_address)) + 1));
  1049.   return (result);
  1050. }
  1051.  
  1052. /*
  1053.   comutil_link is used to initialize all the variable cache slots for
  1054.   a compiled code block.  It is called at load time, by the compiled
  1055.   code itself.  It assumes that the return address has been saved on
  1056.   the stack.
  1057.   If an error occurs during linking, or an interrupt must be processed
  1058.   (because of the need to GC, etc.), it backs out and sets up a return
  1059.   code that will invoke comp_link_caches_restart when the error/interrupt
  1060.   processing is done.
  1061. */
  1062.  
  1063. SCHEME_UTILITY struct utility_result
  1064. DEFUN (comutil_link,
  1065.        (ret_add, block_address, constant_address, sections),
  1066.        instruction *ret_add AND
  1067.        SCHEME_OBJECT *block_address AND SCHEME_OBJECT *constant_address AND
  1068.        long sections)
  1069. {
  1070.   long offset;
  1071.  
  1072.   offset = (constant_address - block_address);
  1073.  
  1074.   RETURN_UNLESS_EXCEPTION
  1075.     ((link_cc_block (block_address,
  1076.                      offset,
  1077.                      offset,
  1078.                      sections,
  1079.                      -1,
  1080.                      ret_add)),
  1081.      ret_add);
  1082. }
  1083.  
  1084. /*
  1085.   comp_link_caches_restart is used to continue the linking process
  1086.   started by comutil_link after the garbage collector has run.
  1087.   It expects the top of the stack to be as left by link_cc_block.
  1088.  */
  1089.  
  1090. C_TO_SCHEME long
  1091. DEFUN_VOID (comp_link_caches_restart)
  1092. {
  1093.   SCHEME_OBJECT block, environment;
  1094.   long original_count, offset, last_header_offset, sections, code;
  1095.   instruction *ret_add;
  1096.  
  1097.   original_count = (OBJECT_DATUM (STACK_POP()));
  1098.   STACK_POP ();                    /* Loop count, for debugger */
  1099.   block = (STACK_POP ());
  1100.   environment = (compiled_block_environment (block));
  1101.   Store_Env (environment);
  1102.   offset = (OBJECT_DATUM (STACK_POP ()));
  1103.   last_header_offset = (OBJECT_DATUM (STACK_POP ()));
  1104.   sections = (OBJECT_DATUM (STACK_POP ()));
  1105.   ret_add = ((instruction *) (OBJECT_ADDRESS (STACK_POP ())));
  1106.   code = (link_cc_block ((OBJECT_ADDRESS (block)),
  1107.                          offset,
  1108.                          last_header_offset,
  1109.                          sections,
  1110.                          original_count,
  1111.                          ret_add));
  1112.   if (code == PRIM_DONE)
  1113.   {
  1114.     /* Return to the block being linked. */
  1115.     return (C_to_interface (ret_add));
  1116.   }
  1117.   else
  1118.   {
  1119.     /* Another GC or error.  We should be ready for back-out. */
  1120.     return (code);
  1121.   }
  1122. }
  1123.  
  1124. /* TRAMPOLINE code
  1125.    When a free variable appears in operator position in compiled code,
  1126.    there must be a directly callable procedure in the corresponding
  1127.    execute cache cell.  If, at link time, there is no appropriate
  1128.    value for the free variable, a fake compiled Scheme procedure that
  1129.    calls one of these procedures will be placed into the cell instead.
  1130.  
  1131.    The trampolines themselves are made by make_uuo_link,
  1132.    make_fake_uuo_link, and coerce_to_compiled.  The trampoline looks
  1133.    like a Scheme closure, containing some code to jump to one of
  1134.    these procedures and additional information to be used by the
  1135.    procedure.
  1136.  
  1137.    These procedures expect a single argument, the address of the
  1138.    information block where they can find the relevant data, typically
  1139.    the procedure to invoke and the number of arguments to invoke it
  1140.    with.
  1141. */
  1142.  
  1143. SCHEME_UTILITY struct utility_result
  1144. DEFUN (comutil_operator_apply_trap,
  1145.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1146.        SCHEME_OBJECT *tramp_data AND
  1147.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1148. {
  1149.   /* Used by coerce_to_compiled.  TRAMPOLINE_K_APPLY */
  1150.  
  1151.   return (comutil_apply ((tramp_data[0]),
  1152.              (OBJECT_DATUM (tramp_data[1])),
  1153.              0, 0));
  1154. }
  1155.  
  1156. SCHEME_UTILITY struct utility_result
  1157. DEFUN (comutil_operator_arity_trap,
  1158.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1159.        SCHEME_OBJECT *tramp_data AND
  1160.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1161. {
  1162.   /* Linker saw an argument count mismatch. TRAMPOLINE_K_ARITY */
  1163.  
  1164.   return (comutil_apply ((tramp_data[0]),
  1165.              (OBJECT_DATUM (tramp_data[1])),
  1166.              0, 0));
  1167. }
  1168.  
  1169. SCHEME_UTILITY struct utility_result
  1170. DEFUN (comutil_operator_entity_trap,
  1171.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1172.        SCHEME_OBJECT *tramp_data AND
  1173.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1174. {
  1175.   /* Linker saw an entity to be applied. TRAMPOLINE_K_ENTITY */
  1176.  
  1177.   return (comutil_apply ((tramp_data[0]),
  1178.              (OBJECT_DATUM (tramp_data[1])),
  1179.              0, 0));
  1180. }
  1181.  
  1182. SCHEME_UTILITY struct utility_result
  1183. DEFUN (comutil_operator_interpreted_trap,
  1184.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1185.        SCHEME_OBJECT *tramp_data AND
  1186.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1187. {
  1188.   /* Linker saw an interpreted procedure or a procedure that it cannot
  1189.      link directly.  TRAMPOLINE_K_INTERPRETED
  1190.    */
  1191.  
  1192.   return (comutil_apply ((tramp_data[0]),
  1193.              (OBJECT_DATUM (tramp_data[1])),
  1194.              0, 0));
  1195. }
  1196.  
  1197. SCHEME_UTILITY struct utility_result
  1198. DEFUN (comutil_operator_lexpr_trap,
  1199.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1200.        SCHEME_OBJECT *tramp_data AND
  1201.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1202. {
  1203.   /* Linker saw a primitive of arbitrary number of arguments.
  1204.      TRAMPOLINE_K_LEXPR_PRIMITIVE
  1205.    */
  1206.  
  1207.   Regs[REGBLOCK_LEXPR_ACTUALS] =
  1208.     ((SCHEME_OBJECT) ((OBJECT_DATUM (tramp_data[1])) - 1));
  1209.   return (comutil_primitive_lexpr_apply ((tramp_data[0]), 0, 0, 0));
  1210. }
  1211.  
  1212. SCHEME_UTILITY struct utility_result
  1213. DEFUN (comutil_operator_primitive_trap,
  1214.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1215.        SCHEME_OBJECT *tramp_data AND
  1216.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1217. {
  1218.   /* Linker saw a primitive of fixed matching arity. TRAMPOLINE_K_PRIMITIVE */
  1219.  
  1220.   return (comutil_primitive_apply ((tramp_data[0]), 0, 0, 0));
  1221. }
  1222.  
  1223. /* The linker either couldn't find a binding or the binding was
  1224.    unassigned, unbound, or a deep-bound (parallel processor) fluid.
  1225.    This must report the correct name of the missing variable and the
  1226.    environment in which the lookup begins for the error cases, or do
  1227.    the correct deep reference for fluids.
  1228.  
  1229.    "extension" is the linker object corresponding to the operator
  1230.    variable (it contains the actual value cell, the name, and linker
  1231.    tables). code_block and offset point to the cache cell in question.
  1232.    tramp_data contains extension, code_block, offset.  TRAMPOLINE_K_LOOKUP
  1233. */
  1234.  
  1235. SCHEME_UTILITY struct utility_result
  1236. DEFUN (comutil_operator_lookup_trap,
  1237.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1238.        SCHEME_OBJECT *tramp_data AND
  1239.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1240. {
  1241.   extern long complr_operator_reference_trap();
  1242.   SCHEME_OBJECT true_operator, *cache_cell;
  1243.   long code, nargs;
  1244.  
  1245.   code = (complr_operator_reference_trap (&true_operator, (tramp_data[0])));
  1246.   cache_cell = (MEMORY_LOC ((tramp_data[1]),
  1247.                 (OBJECT_DATUM (tramp_data[2]))));
  1248.   EXTRACT_EXECUTE_CACHE_ARITY (nargs, cache_cell);
  1249.   if (code == PRIM_DONE)
  1250.   {
  1251.     return (comutil_apply (true_operator, nargs, 0, 0));
  1252.   }
  1253.   else /* Error or interrupt */
  1254.   {
  1255.     SCHEME_OBJECT trampoline, environment, name;
  1256.  
  1257.     /* This could be done by bumpint tramp_data to the entry point.
  1258.        It would probably be better.
  1259.      */
  1260.     EXTRACT_EXECUTE_CACHE_ADDRESS (trampoline, cache_cell);
  1261.     environment = (compiled_block_environment (tramp_data[1]));
  1262.     name = (compiler_var_error ((tramp_data[0]), environment));
  1263.  
  1264.     STACK_PUSH (ENTRY_TO_OBJECT (trampoline));
  1265.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nargs));    /* For debugger */
  1266.     STACK_PUSH (environment);                /* For debugger */
  1267.     STACK_PUSH (name);                    /* For debugger */
  1268.     Store_Expression (SHARP_F);
  1269.     Store_Return (RC_COMP_OP_REF_TRAP_RESTART);
  1270.     Save_Cont ();
  1271.     RETURN_TO_C (code);
  1272.   }
  1273. }
  1274.  
  1275. /*
  1276.   Re-start after processing an error/interrupt encountered in the previous
  1277.   utility.
  1278.   Extract the new trampoline or procedure (the user may have defined the
  1279.   missing variable) and invoke it.
  1280.  */
  1281.  
  1282. C_TO_SCHEME long
  1283. DEFUN_VOID (comp_op_lookup_trap_restart)
  1284. {
  1285.   SCHEME_OBJECT *old_trampoline, code_block, new_procedure;
  1286.   long offset;
  1287.  
  1288.   /* Discard name, env. and nargs */
  1289.  
  1290.   Stack_Pointer = (STACK_LOC (3));
  1291.   old_trampoline = (OBJECT_ADDRESS (STACK_POP ()));
  1292.   code_block = ((TRAMPOLINE_STORAGE (old_trampoline))[1]);
  1293.   offset = (OBJECT_DATUM ((TRAMPOLINE_STORAGE (old_trampoline))[2]));
  1294.   EXTRACT_EXECUTE_CACHE_ADDRESS (new_procedure,
  1295.                  (MEMORY_LOC (code_block, offset)));
  1296.   return (C_to_interface ((instruction *) new_procedure));
  1297. }
  1298.  
  1299. /* ARITY Mismatch handling
  1300.    These receive the entry point as an argument and must fill the
  1301.    Scheme stack with the missing unassigned values.
  1302.    They are invoked by TRAMPOLINE_K_n_m where n and m are the same
  1303.    as in the name of the procedure.
  1304.    The single item of information in the trampoline data area is
  1305.    the real procedure to invoke.  All the arguments are on the
  1306.    Scheme stack.
  1307.  */
  1308.  
  1309. SCHEME_UTILITY struct utility_result
  1310. DEFUN (comutil_operator_1_0_trap,
  1311.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1312.        SCHEME_OBJECT *tramp_data AND
  1313.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1314. {
  1315.   STACK_PUSH (UNASSIGNED_OBJECT);
  1316.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1317. }
  1318.  
  1319. SCHEME_UTILITY struct utility_result
  1320. DEFUN (comutil_operator_2_1_trap,
  1321.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1322.        SCHEME_OBJECT *tramp_data AND
  1323.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1324. {
  1325.   SCHEME_OBJECT Top;
  1326.  
  1327.   Top = STACK_POP ();
  1328.   STACK_PUSH (UNASSIGNED_OBJECT);
  1329.   STACK_PUSH (Top);
  1330.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1331. }
  1332.  
  1333. SCHEME_UTILITY struct utility_result
  1334. DEFUN (comutil_operator_2_0_trap,
  1335.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1336.        SCHEME_OBJECT *tramp_data AND
  1337.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1338. {
  1339.   STACK_PUSH (UNASSIGNED_OBJECT);
  1340.   STACK_PUSH (UNASSIGNED_OBJECT);
  1341.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1342. }
  1343.  
  1344. SCHEME_UTILITY struct utility_result
  1345. DEFUN (comutil_operator_3_2_trap,
  1346.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1347.        SCHEME_OBJECT *tramp_data AND
  1348.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1349. {
  1350.   SCHEME_OBJECT Top, Next;
  1351.  
  1352.   Top = STACK_POP ();
  1353.   Next = STACK_POP ();
  1354.   STACK_PUSH (UNASSIGNED_OBJECT);
  1355.   STACK_PUSH (Next);
  1356.   STACK_PUSH (Top);
  1357.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1358. }
  1359.  
  1360. SCHEME_UTILITY struct utility_result
  1361. DEFUN (comutil_operator_3_1_trap,
  1362.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1363.        SCHEME_OBJECT *tramp_data AND
  1364.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1365. {
  1366.   SCHEME_OBJECT Top;
  1367.  
  1368.   Top = STACK_POP ();
  1369.   STACK_PUSH (UNASSIGNED_OBJECT);
  1370.   STACK_PUSH (UNASSIGNED_OBJECT);
  1371.   STACK_PUSH (Top);
  1372.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1373. }
  1374.  
  1375. SCHEME_UTILITY struct utility_result
  1376. DEFUN (comutil_operator_3_0_trap,
  1377.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1378.        SCHEME_OBJECT *tramp_data AND
  1379.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1380. {
  1381.   STACK_PUSH (UNASSIGNED_OBJECT);
  1382.   STACK_PUSH (UNASSIGNED_OBJECT);
  1383.   STACK_PUSH (UNASSIGNED_OBJECT);
  1384.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1385. }
  1386.  
  1387. SCHEME_UTILITY struct utility_result
  1388. DEFUN (comutil_operator_4_3_trap,
  1389.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1390.        SCHEME_OBJECT *tramp_data AND
  1391.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1392. {
  1393.   SCHEME_OBJECT Top, Middle, Bottom;
  1394.  
  1395.   Top = STACK_POP ();
  1396.   Middle = STACK_POP ();
  1397.   Bottom = STACK_POP ();
  1398.  
  1399.   STACK_PUSH (UNASSIGNED_OBJECT);
  1400.   STACK_PUSH (Bottom);
  1401.   STACK_PUSH (Middle);
  1402.   STACK_PUSH (Top);
  1403.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1404. }
  1405.  
  1406. SCHEME_UTILITY struct utility_result
  1407. DEFUN (comutil_operator_4_2_trap,
  1408.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1409.        SCHEME_OBJECT *tramp_data AND
  1410.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1411. {
  1412.   SCHEME_OBJECT Top, Next;
  1413.  
  1414.   Top = STACK_POP ();
  1415.   Next = STACK_POP ();
  1416.   STACK_PUSH (UNASSIGNED_OBJECT);
  1417.   STACK_PUSH (UNASSIGNED_OBJECT);
  1418.   STACK_PUSH (Next);
  1419.   STACK_PUSH (Top);
  1420.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1421. }
  1422.  
  1423. SCHEME_UTILITY struct utility_result
  1424. DEFUN (comutil_operator_4_1_trap,
  1425.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1426.        SCHEME_OBJECT *tramp_data AND
  1427.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1428. {
  1429.   SCHEME_OBJECT Top;
  1430.  
  1431.   Top = STACK_POP ();
  1432.   STACK_PUSH (UNASSIGNED_OBJECT);
  1433.   STACK_PUSH (UNASSIGNED_OBJECT);
  1434.   STACK_PUSH (UNASSIGNED_OBJECT);
  1435.   STACK_PUSH (Top);
  1436.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1437. }
  1438.  
  1439. SCHEME_UTILITY struct utility_result
  1440. DEFUN (comutil_operator_4_0_trap,
  1441.        (tramp_data, ignore_2, ignore_3, ignore_4),
  1442.        SCHEME_OBJECT *tramp_data AND
  1443.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1444. {
  1445.   STACK_PUSH (UNASSIGNED_OBJECT);
  1446.   STACK_PUSH (UNASSIGNED_OBJECT);
  1447.   STACK_PUSH (UNASSIGNED_OBJECT);
  1448.   STACK_PUSH (UNASSIGNED_OBJECT);
  1449.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1450. }
  1451.  
  1452. /* INTERRUPT/GC from Scheme
  1453.    The next four procedures are called from compiled code at the start
  1454.    (respectively) of a closure, continuation, interpreter compatible
  1455.    procedure, or ordinary (not closed) procedure if an interrupt has
  1456.    been detected.  They return to the interpreter if the interrupt is
  1457.    invalid after saving the state necessary to restart the compiled
  1458.    code.
  1459.  
  1460.    The code that handles RC_COMP_INTERRUPT_RESTART in interp.c will
  1461.    return control to comp_interrupt_restart (below).  This assumes
  1462.    that the Scheme stack contains a compiled code entry address (start
  1463.    of continuation, procedure, etc.).  The Expression register saved
  1464.    with the continuation is a piece of state that will be returned to
  1465.    Val and Env (both) upon return.
  1466. */
  1467.  
  1468. #define GC_DESIRED_P()        (Free >= MemTop)
  1469.  
  1470. #define TEST_GC_NEEDED()                        \
  1471. {                                    \
  1472.   if (GC_DESIRED_P())                            \
  1473.   {                                    \
  1474.     Request_GC(Free-MemTop);                        \
  1475.   }                                    \
  1476. }
  1477.  
  1478. /* Called with no arguments, closure at top of (Scheme) stack.
  1479.    If the interrupt is disabled, the closure is re-invoked.
  1480.  */
  1481.  
  1482. SCHEME_UTILITY struct utility_result
  1483. DEFUN (comutil_interrupt_closure,
  1484.        (ignore_1, ignore_2, ignore_3, ignore_4),
  1485.        long ignore_1 AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1486. {
  1487.   TEST_GC_NEEDED();
  1488.   if ((PENDING_INTERRUPTS()) == 0)
  1489.   {
  1490.     SCHEME_OBJECT entry_point;
  1491.  
  1492.     EXTRACT_CLOSURE_ENTRY_ADDRESS (entry_point,
  1493.                    (OBJECT_ADDRESS (STACK_REF (0))));
  1494.     ADJUST_CLOSURE_AT_CALL (entry_point, (STACK_REF (0)));
  1495.     RETURN_TO_SCHEME (((instruction *) entry_point) +
  1496.               CLOSURE_SKIPPED_CHECK_OFFSET);
  1497.   }
  1498.   else
  1499.   {
  1500.     /* Return to interpreter to handle interrupt */
  1501.     
  1502.     STACK_PUSH (SHARP_F);
  1503.     Store_Expression (SHARP_F);
  1504.     Store_Return (RC_COMP_INTERRUPT_RESTART);
  1505.     Save_Cont ();
  1506.     RETURN_TO_C (PRIM_INTERRUPT);
  1507.   }
  1508. }
  1509.  
  1510. /* State is the live data; no entry point on the stack.
  1511.  */
  1512.  
  1513. static struct utility_result
  1514. DEFUN (compiler_interrupt_common,
  1515.        (entry_point, offset, state),
  1516.        instruction *entry_point AND
  1517.        long offset AND
  1518.        SCHEME_OBJECT state)
  1519. {
  1520.   TEST_GC_NEEDED();
  1521.   if ((PENDING_INTERRUPTS()) == 0)
  1522.   {
  1523.     Store_Env (state);
  1524.     Val = state;
  1525.     RETURN_TO_SCHEME (entry_point + offset);
  1526.   }
  1527.   else
  1528.   {
  1529.     STACK_PUSH (ENTRY_TO_OBJECT (entry_point));
  1530.     STACK_PUSH (state);
  1531.     Store_Expression (SHARP_F);
  1532.     Store_Return (RC_COMP_INTERRUPT_RESTART);
  1533.     Save_Cont ();
  1534.     RETURN_TO_C (PRIM_INTERRUPT);
  1535.   }
  1536. }
  1537.  
  1538. SCHEME_UTILITY struct utility_result
  1539. DEFUN (comutil_interrupt_dlink,
  1540.        (entry_point, dlink, ignore_3, ignore_4),
  1541.        instruction *entry_point AND
  1542.        SCHEME_OBJECT *dlink AND
  1543.        long ignore_3 AND long ignore_4)
  1544. {
  1545.   return
  1546.     (compiler_interrupt_common(entry_point,
  1547.                    ENTRY_SKIPPED_CHECK_OFFSET,
  1548.                    MAKE_POINTER_OBJECT(TC_STACK_ENVIRONMENT,
  1549.                            dlink)));
  1550. }
  1551.  
  1552. SCHEME_UTILITY struct utility_result
  1553. DEFUN (comutil_interrupt_procedure,
  1554.        (entry_point, ignore_2, ignore_3, ignore_4),
  1555.        instruction *entry_point AND
  1556.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1557. {
  1558.   return (compiler_interrupt_common(entry_point,
  1559.                     ENTRY_SKIPPED_CHECK_OFFSET,
  1560.                     SHARP_F));
  1561. }
  1562.  
  1563. /* Val has live data, and there is no entry address on the stack */
  1564.  
  1565. SCHEME_UTILITY struct utility_result
  1566. DEFUN (comutil_interrupt_continuation,
  1567.        (return_address, ignore_2, ignore_3, ignore_4),
  1568.        instruction *return_address AND
  1569.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1570. {
  1571.   return (compiler_interrupt_common (return_address,
  1572.                      ENTRY_SKIPPED_CHECK_OFFSET,
  1573.                      Val));
  1574. }
  1575.  
  1576. /* Env has live data; no entry point on the stack */
  1577.  
  1578. SCHEME_UTILITY struct utility_result
  1579. DEFUN (comutil_interrupt_ic_procedure,
  1580.        (entry_point, ignore_2, ignore_3, ignore_4),
  1581.        instruction *entry_point AND
  1582.        long ignore_2 AND long ignore_3 AND long ignore_4)
  1583. {
  1584.   return (compiler_interrupt_common (entry_point,
  1585.                      ENTRY_SKIPPED_CHECK_OFFSET,
  1586.                      (Fetch_Env())));
  1587. }
  1588.  
  1589. C_TO_SCHEME long
  1590. DEFUN_VOID (comp_interrupt_restart)
  1591. {
  1592.   SCHEME_OBJECT state;
  1593.  
  1594.   state = (STACK_POP ());
  1595.   Store_Env (state);
  1596.   Val = state;
  1597.   return (C_to_interface ((instruction *) (OBJECT_ADDRESS (STACK_POP ()))));
  1598. }
  1599.  
  1600. /* Other TRAPS */
  1601.  
  1602. /* Assigning a variable that has a trap in it (except unassigned) */
  1603.  
  1604. SCHEME_UTILITY struct utility_result
  1605. DEFUN (comutil_assignment_trap,
  1606.        (return_address, extension_addr, value, ignore_4),
  1607.        instruction *return_address AND
  1608.        SCHEME_OBJECT *extension_addr AND SCHEME_OBJECT value AND
  1609.        long ignore_4)
  1610. {
  1611.   extern long compiler_assignment_trap();
  1612.   SCHEME_OBJECT extension;
  1613.   long code;
  1614.  
  1615.   extension = (MAKE_POINTER_OBJECT (TC_QUAD, extension_addr));
  1616.   code = (compiler_assignment_trap (extension, value));
  1617.   if (code == PRIM_DONE)
  1618.   {
  1619.     RETURN_TO_SCHEME (return_address);
  1620.   }
  1621.   else
  1622.   {
  1623.     SCHEME_OBJECT block, environment, name, sra;
  1624.  
  1625.     sra = (ENTRY_TO_OBJECT (return_address));
  1626.     STACK_PUSH (sra);
  1627.     STACK_PUSH (value);
  1628.     block = (compiled_entry_to_block (sra));
  1629.     environment = (compiled_block_environment (block));
  1630.     STACK_PUSH (environment);
  1631.     name = (compiler_var_error (extension, environment));
  1632.     STACK_PUSH (name);
  1633.     Store_Expression (SHARP_F);
  1634.     Store_Return (RC_COMP_ASSIGNMENT_TRAP_RESTART);
  1635.     Save_Cont ();
  1636.     RETURN_TO_C (code);
  1637.   }
  1638. }
  1639.  
  1640. C_TO_SCHEME long
  1641. DEFUN_VOID (comp_assignment_trap_restart)
  1642. {
  1643.   extern long Symbol_Lex_Set();
  1644.   SCHEME_OBJECT name, environment, value;
  1645.   long code;
  1646.  
  1647.   name = (STACK_POP ());
  1648.   environment = (STACK_POP ());
  1649.   value = (STACK_POP ());
  1650.   code = (Symbol_Lex_Set (environment, name, value));
  1651.   if (code == PRIM_DONE)
  1652.   {
  1653.     return (C_to_interface (OBJECT_ADDRESS (STACK_POP ())));
  1654.   }
  1655.   else
  1656.   {
  1657.     STACK_PUSH (value);
  1658.     STACK_PUSH (environment);
  1659.     STACK_PUSH (name);
  1660.     Store_Expression (SHARP_F);
  1661.     Store_Return (RC_COMP_ASSIGNMENT_TRAP_RESTART);
  1662.     Save_Cont ();
  1663.     return (code);
  1664.   }
  1665. }
  1666.  
  1667. SCHEME_UTILITY struct utility_result
  1668. DEFUN (comutil_cache_lookup_apply,
  1669.        (extension_addr, block_address, nactuals, ignore_4),
  1670.        SCHEME_OBJECT *extension_addr AND SCHEME_OBJECT *block_address AND
  1671.        long nactuals AND long ignore_4)
  1672. {
  1673.   extern long compiler_lookup_trap();
  1674.   SCHEME_OBJECT extension;
  1675.   long code;
  1676.  
  1677.   extension = (MAKE_POINTER_OBJECT (TC_QUAD, extension_addr));
  1678.   code = (compiler_lookup_trap (extension));
  1679.   if (code == PRIM_DONE)
  1680.   {
  1681.     return (comutil_apply (Val, nactuals, 0, 0));
  1682.   }
  1683.   else
  1684.   {
  1685.     SCHEME_OBJECT block, environment, name;
  1686.  
  1687.     block = (MAKE_CC_BLOCK (block_address));
  1688.     STACK_PUSH (block);
  1689.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  1690.     environment = (compiled_block_environment (block));
  1691.     STACK_PUSH (environment);
  1692.     name = (compiler_var_error (extension, environment));
  1693.     STACK_PUSH (name);
  1694.     Store_Expression (SHARP_F);
  1695.     Store_Return (RC_COMP_CACHE_REF_APPLY_RESTART);
  1696.     Save_Cont ();
  1697.     RETURN_TO_C (code);
  1698.   }
  1699. }
  1700.  
  1701. C_TO_SCHEME long
  1702. DEFUN_VOID (comp_cache_lookup_apply_restart)
  1703. {
  1704.   extern long Symbol_Lex_Ref();
  1705.   SCHEME_OBJECT name, environment, block;
  1706.   long code;
  1707.  
  1708.   name = (STACK_POP ());
  1709.   environment = (STACK_POP ());
  1710.   code = (Symbol_Lex_Ref (environment, name));
  1711.   if (code == PRIM_DONE)
  1712.   {
  1713.     /* Replace block with actual operator */
  1714.     (*(STACK_LOC (1))) = Val;
  1715.     if (COMPILED_CODE_ADDRESS_P (Val))
  1716.     {
  1717.       return (apply_compiled_procedure ());
  1718.     }
  1719.     else
  1720.     {
  1721.       return (PRIM_APPLY);
  1722.     }
  1723.   }
  1724.   else
  1725.   {
  1726.     STACK_PUSH (environment);
  1727.     STACK_PUSH (name);
  1728.     Store_Expression (SHARP_F);
  1729.     Store_Return (RC_COMP_CACHE_REF_APPLY_RESTART);
  1730.     Save_Cont ();
  1731.     return (code);
  1732.   }
  1733. }
  1734.  
  1735. /* Variable reference traps:
  1736.    Reference to a free variable that has a reference trap -- either a
  1737.    fluid or an error (unassigned / unbound)
  1738.  */
  1739.  
  1740. #define CMPLR_REF_TRAP(name, c_trap, ret_code, restart, c_lookup)    \
  1741. SCHEME_UTILITY struct utility_result                    \
  1742. DEFUN (name,                                \
  1743.        (return_address, extension_addr, ignore_3, ignore_4),        \
  1744.        instruction *return_address AND                    \
  1745.        SCHEME_OBJECT *extension_addr AND                \
  1746.        long ignore_3 AND long ignore_4)                    \
  1747. {                                    \
  1748.   extern long c_trap();                            \
  1749.   long code;                                \
  1750.   SCHEME_OBJECT extension;                        \
  1751.                                     \
  1752.   extension = (MAKE_POINTER_OBJECT (TC_QUAD, extension_addr));        \
  1753.   code = c_trap (extension);                        \
  1754.   if (code == PRIM_DONE)                        \
  1755.   {                                    \
  1756.     RETURN_TO_SCHEME (return_address);                    \
  1757.   }                                    \
  1758.   else                                    \
  1759.   {                                    \
  1760.     SCHEME_OBJECT block, environment, name, sra;            \
  1761.                                     \
  1762.     sra = (ENTRY_TO_OBJECT (return_address));                \
  1763.     STACK_PUSH (sra);                            \
  1764.     block = (compiled_entry_to_block (sra));                \
  1765.     environment = (compiled_block_environment (block));            \
  1766.     STACK_PUSH (environment);                        \
  1767.     name = (compiler_var_error (extension, environment));        \
  1768.     STACK_PUSH (name);                            \
  1769.     Store_Expression (SHARP_F);                        \
  1770.     Store_Return (ret_code);                        \
  1771.     Save_Cont ();                            \
  1772.     RETURN_TO_C (code);                            \
  1773.   }                                    \
  1774. }                                    \
  1775.                                     \
  1776. C_TO_SCHEME long                            \
  1777. DEFUN_VOID (restart)                            \
  1778. {                                    \
  1779.   extern long c_lookup();                        \
  1780.   SCHEME_OBJECT name, environment;                    \
  1781.   long code;                                \
  1782.                                     \
  1783.   name = (Fetch_Expression ());                        \
  1784.   environment = (STACK_POP ());                        \
  1785.   code = (c_lookup (environment, name));                \
  1786.   if (code == PRIM_DONE)                        \
  1787.   {                                    \
  1788.     return (C_to_interface (OBJECT_ADDRESS (STACK_POP ())));        \
  1789.   }                                    \
  1790.   else                                    \
  1791.   {                                    \
  1792.     STACK_PUSH (environment);                        \
  1793.     STACK_PUSH (name);                            \
  1794.     Store_Expression (SHARP_F);                        \
  1795.     Store_Return (ret_code);                        \
  1796.     Save_Cont ();                            \
  1797.     return (code);                            \
  1798.   }                                    \
  1799. }
  1800.  
  1801. /* Actual traps */
  1802.  
  1803. CMPLR_REF_TRAP(comutil_lookup_trap,
  1804.                compiler_lookup_trap,
  1805.                RC_COMP_LOOKUP_TRAP_RESTART,
  1806.                comp_lookup_trap_restart,
  1807.                Symbol_Lex_Ref);
  1808.  
  1809. CMPLR_REF_TRAP(comutil_safe_lookup_trap,
  1810.                compiler_safe_lookup_trap,
  1811.                RC_COMP_SAFE_REF_TRAP_RESTART,
  1812.                comp_safe_lookup_trap_restart,
  1813.                safe_symbol_lex_ref);
  1814.  
  1815. CMPLR_REF_TRAP(comutil_unassigned_p_trap,
  1816.                compiler_unassigned_p_trap,
  1817.                RC_COMP_UNASSIGNED_TRAP_RESTART,
  1818.                comp_unassigned_p_trap_restart,
  1819.                Symbol_Lex_unassigned_p);
  1820.  
  1821. /* NUMERIC ROUTINES
  1822.    Invoke the arithmetic primitive in the fixed objects vector.
  1823.    The Scheme arguments are expected on the Scheme stack.
  1824.  */
  1825.  
  1826. #define COMPILER_ARITH_PRIM(name, fobj_index, arity)            \
  1827. SCHEME_UTILITY struct utility_result                    \
  1828. DEFUN (name,                                \
  1829.        (ignore_1, ignore_2, ignore_3, ignore_4),            \
  1830.        long ignore_1 AND long ignore_2 AND                \
  1831.        long ignore_3 AND long ignore_4)                    \
  1832. {                                    \
  1833.   SCHEME_OBJECT handler;                        \
  1834.                                     \
  1835.   handler = (Get_Fixed_Obj_Slot (fobj_index));                \
  1836.   return (comutil_apply (handler, (arity), 0, 0));            \
  1837. }
  1838.  
  1839. COMPILER_ARITH_PRIM (comutil_decrement, GENERIC_TRAMPOLINE_PREDECESSOR, 2);
  1840. COMPILER_ARITH_PRIM (comutil_divide, GENERIC_TRAMPOLINE_DIVIDE, 3);
  1841. COMPILER_ARITH_PRIM (comutil_equal, GENERIC_TRAMPOLINE_EQUAL_P, 3);
  1842. COMPILER_ARITH_PRIM (comutil_greater, GENERIC_TRAMPOLINE_GREATER_P, 3);
  1843. COMPILER_ARITH_PRIM (comutil_increment, GENERIC_TRAMPOLINE_SUCCESSOR, 2);
  1844. COMPILER_ARITH_PRIM (comutil_less, GENERIC_TRAMPOLINE_LESS_P, 3);
  1845. COMPILER_ARITH_PRIM (comutil_minus, GENERIC_TRAMPOLINE_SUBTRACT, 3);
  1846. COMPILER_ARITH_PRIM (comutil_modulo, GENERIC_TRAMPOLINE_MODULO, 3);
  1847. COMPILER_ARITH_PRIM (comutil_multiply, GENERIC_TRAMPOLINE_MULTIPLY, 3);
  1848. COMPILER_ARITH_PRIM (comutil_negative, GENERIC_TRAMPOLINE_NEGATIVE_P, 2);
  1849. COMPILER_ARITH_PRIM (comutil_plus, GENERIC_TRAMPOLINE_ADD, 3);
  1850. COMPILER_ARITH_PRIM (comutil_positive, GENERIC_TRAMPOLINE_POSITIVE_P, 2);
  1851. COMPILER_ARITH_PRIM (comutil_quotient, GENERIC_TRAMPOLINE_QUOTIENT, 3);
  1852. COMPILER_ARITH_PRIM (comutil_remainder, GENERIC_TRAMPOLINE_REMAINDER, 3);
  1853. COMPILER_ARITH_PRIM (comutil_zero, GENERIC_TRAMPOLINE_ZERO_P, 2);
  1854.  
  1855. /*
  1856.   Obsolete SCHEME_UTILITYs used to handle first class environments.
  1857.   They have been superseded by the variable caching code.
  1858.   They are here for completeness, and because the code in the compiler
  1859.   that uses them has not yet been spliced out, although it is switched
  1860.   off.
  1861. */
  1862.  
  1863. #define CMPLR_REFERENCE(util_name, c_proc, ret_code, restart_name)    \
  1864. SCHEME_UTILITY struct utility_result                    \
  1865. DEFUN (util_name,                            \
  1866.        (ret_add, environment, variable, ignore_4),            \
  1867.        instruction *ret_add AND                        \
  1868.        SCHEME_OBJECT environment AND SCHEME_OBJECT variable AND        \
  1869.        long ignore_4)                            \
  1870. {                                    \
  1871.   extern long c_proc();                            \
  1872.   long code;                                \
  1873.                                     \
  1874.   code = (c_proc (environment, variable));                \
  1875.   if (code == PRIM_DONE)                        \
  1876.   {                                    \
  1877.     RETURN_TO_SCHEME (ret_add);                        \
  1878.   }                                    \
  1879.   else                                    \
  1880.   {                                    \
  1881.     STACK_PUSH (ENTRY_TO_OBJECT (ret_add));                \
  1882.     STACK_PUSH (variable);                        \
  1883.     STACK_PUSH (environment);                        \
  1884.     Store_Expression (SHARP_F);                        \
  1885.     Store_Return (ret_code);                        \
  1886.     Save_Cont ();                            \
  1887.     RETURN_TO_C (code);                            \
  1888.   }                                    \
  1889. }                                    \
  1890.                                     \
  1891. C_TO_SCHEME long                            \
  1892. DEFUN_VOID (restart_name)                        \
  1893. {                                    \
  1894.   extern long c_proc();                            \
  1895.   SCHEME_OBJECT environment, variable;                    \
  1896.   long code;                                \
  1897.                                     \
  1898.   environment = (STACK_POP ());                        \
  1899.   variable = (STACK_POP ());                        \
  1900.   code = (c_proc (environment, variable));                \
  1901.   if (code == PRIM_DONE)                        \
  1902.   {                                    \
  1903.     Regs[REGBLOCK_ENV] = environment;                    \
  1904.     return (C_to_interface (OBJECT_ADDRESS (STACK_POP ())));        \
  1905.   }                                    \
  1906.   else                                    \
  1907.   {                                    \
  1908.     STACK_PUSH (variable);                        \
  1909.     STACK_PUSH (environment);                        \
  1910.     Store_Expression (SHARP_F);                        \
  1911.     Store_Return (ret_code);                        \
  1912.     Save_Cont ();                            \
  1913.     return (code);                            \
  1914.   }                                    \
  1915. }
  1916.  
  1917. #define CMPLR_ASSIGNMENT(util_name, c_proc, ret_code, restart_name)    \
  1918. SCHEME_UTILITY struct utility_result                    \
  1919. DEFUN (util_name,                            \
  1920.        (ret_add, environment, variable, value),                \
  1921.        instruction *ret_add AND                        \
  1922.        SCHEME_OBJECT environment AND SCHEME_OBJECT variable        \
  1923.        AND SCHEME_OBJECT value)                        \
  1924. {                                    \
  1925.   extern long c_proc();                            \
  1926.   long code;                                \
  1927.                                     \
  1928.   code = (c_proc (environment, variable, value));            \
  1929.   if (code == PRIM_DONE)                        \
  1930.   {                                    \
  1931.     RETURN_TO_SCHEME (ret_add);                        \
  1932.   }                                    \
  1933.   else                                    \
  1934.   {                                    \
  1935.     STACK_PUSH (ENTRY_TO_OBJECT (ret_add));                \
  1936.     STACK_PUSH (value);                            \
  1937.     STACK_PUSH (variable);                        \
  1938.     STACK_PUSH (environment);                        \
  1939.     Store_Expression (SHARP_F);                        \
  1940.     Store_Return (ret_code);                        \
  1941.     Save_Cont ();                            \
  1942.     RETURN_TO_C (code);                            \
  1943.   }                                    \
  1944. }                                    \
  1945.                                     \
  1946. C_TO_SCHEME long                            \
  1947. DEFUN_VOID (restart_name)                        \
  1948. {                                    \
  1949.   extern long c_proc();                            \
  1950.   SCHEME_OBJECT environment, variable, value;                \
  1951.   long code;                                \
  1952.                                     \
  1953.   environment = (Fetch_Expression ());                    \
  1954.   variable = (STACK_POP ());                        \
  1955.   value = (STACK_POP ());                        \
  1956.   code = (c_proc (environment, variable, value));            \
  1957.   if (code == PRIM_DONE)                        \
  1958.   {                                    \
  1959.     Regs[REGBLOCK_ENV] = environment;                    \
  1960.     return (C_to_interface (OBJECT_ADDRESS (STACK_POP ())));        \
  1961.   }                                    \
  1962.   else                                    \
  1963.   {                                    \
  1964.     STACK_PUSH (value);                            \
  1965.     STACK_PUSH (variable);                        \
  1966.     STACK_PUSH (environment);                        \
  1967.     Store_Expression (SHARP_F);                        \
  1968.     Store_Return (ret_code);                        \
  1969.     Save_Cont ();                            \
  1970.     return (code);                            \
  1971.   }                                    \
  1972. }
  1973.  
  1974. CMPLR_REFERENCE(comutil_access,
  1975.         Symbol_Lex_Ref,
  1976.         RC_COMP_ACCESS_RESTART,
  1977.         comp_access_restart);
  1978.  
  1979. CMPLR_REFERENCE(comutil_reference,
  1980.         Lex_Ref,
  1981.         RC_COMP_REFERENCE_RESTART,
  1982.         comp_reference_restart);
  1983.  
  1984. CMPLR_REFERENCE(comutil_safe_reference,
  1985.         safe_lex_ref,
  1986.         RC_COMP_SAFE_REFERENCE_RESTART,
  1987.         comp_safe_reference_restart);
  1988.  
  1989. CMPLR_REFERENCE(comutil_unassigned_p,
  1990.         Symbol_Lex_unassigned_p,
  1991.         RC_COMP_UNASSIGNED_P_RESTART,
  1992.         comp_unassigned_p_restart);
  1993.  
  1994. CMPLR_REFERENCE(comutil_unbound_p,
  1995.         Symbol_Lex_unbound_p,
  1996.         RC_COMP_UNBOUND_P_RESTART,
  1997.         comp_unbound_p_restart);
  1998.  
  1999. CMPLR_ASSIGNMENT(comutil_assignment,
  2000.          Lex_Set,
  2001.          RC_COMP_ASSIGNMENT_RESTART,
  2002.          comp_assignment_restart);
  2003.  
  2004. CMPLR_ASSIGNMENT(comutil_definition,
  2005.          Local_Set,
  2006.          RC_COMP_DEFINITION_RESTART,
  2007.          comp_definition_restart);
  2008.  
  2009. SCHEME_UTILITY struct utility_result
  2010. DEFUN (comutil_lookup_apply,
  2011.        (environment, variable, nactuals, ignore_4),
  2012.        SCHEME_OBJECT environment AND SCHEME_OBJECT variable AND
  2013.        long nactuals AND long ignore_4)
  2014. {
  2015.   extern long Lex_Ref();
  2016.   long code;
  2017.  
  2018.   code = (Lex_Ref (environment, variable));
  2019.   if (code == PRIM_DONE)
  2020.   {
  2021.     return (comutil_apply (Val, nactuals, 0, 0));
  2022.   }
  2023.   else
  2024.   {
  2025.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  2026.     STACK_PUSH (variable);
  2027.     STACK_PUSH (environment);
  2028.     Store_Expression (SHARP_F);
  2029.     Store_Return (RC_COMP_LOOKUP_APPLY_RESTART);
  2030.     Save_Cont ();
  2031.     RETURN_TO_C (code);
  2032.   }
  2033. }
  2034.  
  2035. C_TO_SCHEME long
  2036. DEFUN_VOID (comp_lookup_apply_restart)
  2037. {
  2038.   extern long Lex_Ref();
  2039.   SCHEME_OBJECT environment, variable;
  2040.   long code;
  2041.  
  2042.   environment = (STACK_POP ());
  2043.   variable = (STACK_POP ());
  2044.   code = (Lex_Ref (environment, variable));
  2045.   if (code == PRIM_DONE)
  2046.   {
  2047.     SCHEME_OBJECT nactuals;
  2048.  
  2049.     nactuals = (STACK_POP ());
  2050.     STACK_PUSH (Val);
  2051.     STACK_PUSH (nactuals);
  2052.     if (COMPILED_CODE_ADDRESS_P (Val))
  2053.     {
  2054.       return (apply_compiled_procedure ());
  2055.     }
  2056.     else
  2057.     {
  2058.       return (PRIM_APPLY);
  2059.     }
  2060.   }
  2061.   else
  2062.   {
  2063.     STACK_PUSH (variable);
  2064.     STACK_PUSH (environment);
  2065.     Store_Expression (SHARP_F);
  2066.     Store_Return (RC_COMP_LOOKUP_APPLY_RESTART);
  2067.     Save_Cont ();
  2068.     return (code);
  2069.   }
  2070. }
  2071.  
  2072. SCHEME_UTILITY struct utility_result
  2073. DEFUN (comutil_primitive_error,
  2074.        (ret_add, primitive, ignore_3, ignore_4),
  2075.        instruction *ret_add AND
  2076.        SCHEME_OBJECT primitive AND
  2077.        long ignore_3 AND long ignore_4)
  2078. {
  2079.   STACK_PUSH (ENTRY_TO_OBJECT (ret_add));
  2080.   STACK_PUSH (primitive);
  2081.   Store_Expression (SHARP_F);
  2082.   Store_Return (RC_COMP_ERROR_RESTART);
  2083.   Save_Cont ();
  2084.   RETURN_TO_C (ERR_COMPILED_CODE_ERROR);
  2085. }
  2086.  
  2087. C_TO_SCHEME long
  2088. DEFUN_VOID (comp_error_restart)
  2089. {
  2090.   instruction *ret_add;
  2091.  
  2092.   STACK_POP ();            /* primitive */
  2093.   ret_add = ((instruction *) (OBJECT_ADDRESS (STACK_POP ())));
  2094.   return (C_to_interface (ret_add));
  2095. }
  2096.  
  2097. /* Procedures to destructure compiled entries and closures. */
  2098.  
  2099. /*
  2100.   Extract the debugging information attached to `block'.  Usually
  2101.   this is a string which contains the filename where the debugging
  2102.   info is stored.
  2103.  */
  2104.  
  2105. C_UTILITY SCHEME_OBJECT
  2106. DEFUN (compiled_block_debugging_info,
  2107.        (block),
  2108.        SCHEME_OBJECT block)
  2109. {
  2110.   long length;
  2111.  
  2112.   length = (VECTOR_LENGTH (block));
  2113.   return (FAST_MEMORY_REF (block, (length - 1)));
  2114. }
  2115.  
  2116. /* Extract the environment where the `block' was "loaded". */
  2117.  
  2118. C_UTILITY SCHEME_OBJECT
  2119. DEFUN (compiled_block_environment,
  2120.        (block),
  2121.        SCHEME_OBJECT block)
  2122. {
  2123.   long length;
  2124.  
  2125.   length = (VECTOR_LENGTH (block));
  2126.   return (FAST_MEMORY_REF (block, length));
  2127. }
  2128.  
  2129. /*
  2130.   Given `entry', a Scheme object representing a compiled code entry point,
  2131.   it returns the address of the block to which it belongs.
  2132.  */
  2133.  
  2134. C_UTILITY SCHEME_OBJECT *
  2135. DEFUN (compiled_entry_to_block_address,
  2136.        (entry),
  2137.        SCHEME_OBJECT entry)
  2138. {
  2139.   SCHEME_OBJECT *block_address;
  2140.  
  2141.   Get_Compiled_Block (block_address, (OBJECT_ADDRESS (entry)));
  2142.   return (block_address);
  2143. }
  2144.  
  2145. C_UTILITY SCHEME_OBJECT
  2146. DEFUN (compiled_entry_to_block,
  2147.        (entry),
  2148.        SCHEME_OBJECT entry)
  2149. {
  2150.   SCHEME_OBJECT *block_address;
  2151.  
  2152.   Get_Compiled_Block (block_address, (OBJECT_ADDRESS (entry)));
  2153.   return (MAKE_CC_BLOCK (block_address));
  2154. }
  2155.  
  2156. /* Returns the offset from the block to the entry point. */
  2157.  
  2158. C_UTILITY long
  2159. DEFUN (compiled_entry_to_block_offset,
  2160.        (entry),
  2161.        SCHEME_OBJECT entry)
  2162. {
  2163.   SCHEME_OBJECT *entry_address, *block_address;
  2164.  
  2165.   entry_address = (OBJECT_ADDRESS (entry));
  2166.   Get_Compiled_Block (block_address, entry_address);
  2167.   return (((char *) entry_address) - ((char *) block_address));
  2168. }
  2169.  
  2170. /*
  2171.   Check whether the compiled code block whose address is `block_addr'
  2172.   is a compiled closure block.
  2173.  */
  2174.  
  2175. static long
  2176. DEFUN (block_address_closure_p,
  2177.        (block_addr),
  2178.        SCHEME_OBJECT *block_addr)
  2179. {
  2180.   SCHEME_OBJECT header_word;
  2181.  
  2182.   header_word = (*block_addr);
  2183.   return (((OBJECT_TYPE (header_word)) == TC_MANIFEST_CLOSURE));
  2184. }
  2185.  
  2186. /*
  2187.   Check whether the compiled code block `block' is a compiled closure block.
  2188.  */
  2189.  
  2190. C_UTILITY long
  2191. DEFUN (compiled_block_closure_p,
  2192.        (block),
  2193.        SCHEME_OBJECT block)
  2194. {
  2195.   return (block_address_closure_p (OBJECT_ADDRESS (block)));
  2196. }
  2197.  
  2198. /*
  2199.   Check whether the compiled entry point `entry' is a compiled closure.
  2200.  */
  2201.  
  2202. C_UTILITY long
  2203. DEFUN (compiled_entry_closure_p,
  2204.        (entry),
  2205.        SCHEME_OBJECT entry)
  2206. {
  2207.   return (block_address_closure_p (compiled_entry_to_block_address (entry)));
  2208. }
  2209.  
  2210. /*
  2211.   Extract the entry point ultimately invoked by the compiled closure
  2212.   represented by `entry'.
  2213.  */
  2214.  
  2215. C_UTILITY SCHEME_OBJECT
  2216. DEFUN (compiled_closure_to_entry,
  2217.        (entry),
  2218.        SCHEME_OBJECT entry)
  2219. {
  2220.   SCHEME_OBJECT real_entry;
  2221.  
  2222.   EXTRACT_CLOSURE_ENTRY_ADDRESS (real_entry, (OBJECT_ADDRESS (entry)));
  2223.   return (ENTRY_TO_OBJECT (real_entry));
  2224. }
  2225.  
  2226. /*
  2227.   Store the information for `entry' into `buffer'.
  2228.   This is used by the printer and debugging utilities.
  2229.  */
  2230.  
  2231. /* Kinds and subkinds of entries. */
  2232.  
  2233. #define KIND_PROCEDURE                          0
  2234. #define KIND_CONTINUATION                       1
  2235. #define KIND_EXPRESSION                         2
  2236. #define KIND_OTHER                              3
  2237. #define KIND_ILLEGAL                            4
  2238.  
  2239. /* Continuation subtypes */
  2240.  
  2241. #define CONTINUATION_NORMAL                     0
  2242. #define CONTINUATION_DYNAMIC_LINK               1
  2243. #define CONTINUATION_RETURN_TO_INTERPRETER      2
  2244.  
  2245. C_UTILITY void
  2246. DEFUN (compiled_entry_type,
  2247.        (entry, buffer),
  2248.        SCHEME_OBJECT entry AND
  2249.        long *buffer)
  2250. {
  2251.   long kind, min_arity, max_arity, field1, field2;
  2252.   SCHEME_OBJECT *entry_address;
  2253.  
  2254.   entry_address = (OBJECT_ADDRESS (entry));
  2255.   max_arity = (COMPILED_ENTRY_MAXIMUM_ARITY (entry_address));
  2256.   min_arity = (COMPILED_ENTRY_MINIMUM_ARITY (entry_address));
  2257.   field1 = min_arity;
  2258.   field2 = max_arity;
  2259.   if (min_arity >= 0)
  2260.   {
  2261.     kind = KIND_PROCEDURE;
  2262.   }
  2263.   else if (max_arity >= 0)
  2264.   {
  2265.     kind = KIND_ILLEGAL;
  2266.   }
  2267.   else if ((((unsigned long) max_arity) & 0xff) < 0xe0)
  2268.   {
  2269.     /* Field2 is the offset to the next continuation */
  2270.  
  2271.     kind = KIND_CONTINUATION;
  2272.     field1 = CONTINUATION_NORMAL;
  2273.     field2 = (((((unsigned long) max_arity) & 0x3f) << 7) |
  2274.               (((unsigned long) min_arity) & 0x7f));
  2275.   }
  2276.   else if (min_arity != (-1))
  2277.   {
  2278.     kind = KIND_ILLEGAL;
  2279.   }
  2280.   else
  2281.   {
  2282.     switch (((unsigned long) max_arity) & 0xff)
  2283.     {
  2284.       case FORMAT_BYTE_EXPR:
  2285.       {
  2286.         kind = KIND_EXPRESSION;
  2287.         break;
  2288.       }
  2289.       case FORMAT_BYTE_COMPLR:
  2290.       case FORMAT_BYTE_CMPINT:
  2291.       {
  2292.         kind = KIND_OTHER;
  2293.         break;
  2294.       }
  2295.       case FORMAT_BYTE_DLINK:
  2296.       {
  2297.         kind = KIND_CONTINUATION;
  2298.         field1 = CONTINUATION_DYNAMIC_LINK;
  2299.         field2 = -1;
  2300.         break;
  2301.       }
  2302.       case FORMAT_BYTE_RETURN:
  2303.       {
  2304.         kind = KIND_CONTINUATION;
  2305.         field1 = CONTINUATION_RETURN_TO_INTERPRETER;
  2306.         field2 = 0;
  2307.         break;
  2308.       }
  2309.       default:
  2310.       {
  2311.         kind = KIND_ILLEGAL;
  2312.         break;
  2313.       }
  2314.     }
  2315.   }
  2316.   buffer[0] = kind;
  2317.   buffer[1] = field1;
  2318.   buffer[2] = field2;
  2319.   return;
  2320. }
  2321.  
  2322. /* Destructuring free variable caches. */
  2323.  
  2324. C_UTILITY void
  2325. DEFUN (store_variable_cache,
  2326.        (extension, block, offset),
  2327.        SCHEME_OBJECT extension AND SCHEME_OBJECT block AND
  2328.        long offset)
  2329. {
  2330.   FAST_MEMORY_SET (block, offset,
  2331.                    ((SCHEME_OBJECT) (OBJECT_ADDRESS (extension))));
  2332.   return;
  2333. }
  2334.  
  2335. C_UTILITY SCHEME_OBJECT
  2336. DEFUN (extract_variable_cache,
  2337.        (block, offset),
  2338.        SCHEME_OBJECT block AND
  2339.        long offset)
  2340. {
  2341.   return (MAKE_POINTER_OBJECT (TRAP_EXTENSION_TYPE,
  2342.                                ((SCHEME_OBJECT *)
  2343.                                 (FAST_MEMORY_REF (block, offset)))));
  2344. }
  2345.  
  2346. /* Get a compiled procedure from a cached operator reference. */
  2347.  
  2348. C_UTILITY SCHEME_OBJECT
  2349. DEFUN (extract_uuo_link,
  2350.        (block, offset),
  2351.        SCHEME_OBJECT block AND
  2352.        long offset)
  2353. {
  2354.   SCHEME_OBJECT *cache_address, compiled_entry_address;
  2355.  
  2356.   cache_address = (MEMORY_LOC (block, offset));
  2357.   EXTRACT_EXECUTE_CACHE_ADDRESS (compiled_entry_address, cache_address);
  2358.   return (ENTRY_TO_OBJECT (compiled_entry_address));
  2359. }
  2360.  
  2361. static void
  2362. DEFUN (store_uuo_link,
  2363.        (entry, cache_address),
  2364.        SCHEME_OBJECT entry AND SCHEME_OBJECT *cache_address)
  2365. {
  2366.   SCHEME_OBJECT *entry_address;
  2367.  
  2368.   entry_address = (OBJECT_ADDRESS (entry));
  2369.   STORE_EXECUTE_CACHE_CODE (cache_address);
  2370.   STORE_EXECUTE_CACHE_ADDRESS (cache_address, entry_address);
  2371.   if (!linking_cc_block_p)
  2372.   {
  2373.     /* The linker will flush the whole region afterwards. */
  2374.  
  2375.     FLUSH_I_CACHE_REGION (cache_address, EXECUTE_CACHE_ENTRY_SIZE);
  2376.   }
  2377.   return;
  2378. }
  2379.  
  2380. /* This makes a fake compiled procedure which traps to kind handler when
  2381.    invoked.
  2382.  */
  2383.  
  2384. #define TRAMPOLINE_SIZE    (TRAMPOLINE_ENTRY_SIZE + 2)
  2385.  
  2386. static long
  2387. DEFUN (make_trampoline,
  2388.        (slot, fmt_word, kind, size, value1, value2, value3),
  2389.        SCHEME_OBJECT *slot AND
  2390.        format_word fmt_word AND
  2391.        long kind AND long size AND
  2392.        SCHEME_OBJECT value1 AND SCHEME_OBJECT value2
  2393.        AND SCHEME_OBJECT value3)
  2394. {
  2395.   SCHEME_OBJECT * block, * local_free;
  2396.   instruction * entry_point;
  2397.  
  2398.   if (GC_Check (TRAMPOLINE_SIZE + size))
  2399.   {
  2400.     Request_GC (TRAMPOLINE_SIZE + size);
  2401.     return (PRIM_INTERRUPT);
  2402.   }
  2403.  
  2404.   local_free = Free;
  2405.   Free += (TRAMPOLINE_SIZE + size);
  2406.   block = local_free;
  2407.   local_free[0] = (MAKE_OBJECT (TC_MANIFEST_VECTOR,
  2408.                 ((TRAMPOLINE_SIZE - 1) + size)));
  2409.   local_free[1] = (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR,
  2410.                 TRAMPOLINE_ENTRY_SIZE));
  2411.   entry_point = ((instruction *) (TRAMPOLINE_ENTRY_POINT (local_free)));
  2412.   local_free = (TRAMPOLINE_STORAGE (entry_point));
  2413.   (COMPILED_ENTRY_FORMAT_WORD (entry_point)) = fmt_word;
  2414.   (COMPILED_ENTRY_OFFSET_WORD (entry_point)) =
  2415.     (MAKE_OFFSET_WORD (entry_point, block, false));
  2416.   STORE_TRAMPOLINE_ENTRY (entry_point, kind);
  2417.  
  2418.   if ((--size) >= 0)
  2419.     *local_free++ = value1;
  2420.   if ((--size) >= 0)
  2421.     *local_free++ = value2;
  2422.   if ((--size) >= 0)
  2423.     *local_free++ = value3;
  2424.   *slot = (ENTRY_TO_OBJECT (entry_point));
  2425.   return (PRIM_DONE);
  2426. }
  2427.  
  2428. /* Standard trampolines. */
  2429.  
  2430. static long
  2431. DEFUN (make_redirection_trampoline,
  2432.        (slot, kind, procedure),
  2433.        SCHEME_OBJECT *slot AND
  2434.        long kind AND
  2435.        SCHEME_OBJECT procedure)
  2436. {
  2437.   return (make_trampoline (slot,
  2438.                ((format_word) FORMAT_WORD_CMPINT),
  2439.                kind,
  2440.                1,
  2441.                procedure,
  2442.                SHARP_F,
  2443.                SHARP_F));
  2444. }
  2445.  
  2446. static long
  2447. DEFUN (make_apply_trampoline,
  2448.        (slot, kind, procedure, nactuals),
  2449.        SCHEME_OBJECT *slot AND
  2450.        long kind AND SCHEME_OBJECT procedure AND
  2451.        long nactuals)
  2452. {
  2453.   return (make_trampoline (slot,
  2454.                ((format_word) FORMAT_WORD_CMPINT),
  2455.                kind,
  2456.                2,
  2457.                procedure,
  2458.                (LONG_TO_UNSIGNED_FIXNUM (nactuals)),
  2459.                SHARP_F));
  2460. }
  2461.  
  2462. #define TRAMPOLINE_TABLE_SIZE   4
  2463.  
  2464. static long
  2465. trampoline_arity_table[TRAMPOLINE_TABLE_SIZE * TRAMPOLINE_TABLE_SIZE] =
  2466. {
  2467.   TRAMPOLINE_K_1_0,        /* 1_0 */
  2468.   TRAMPOLINE_K_ARITY,        /* 1_1 should not get here */
  2469.   TRAMPOLINE_K_ARITY,        /* 1_2 should not get here */
  2470.   TRAMPOLINE_K_ARITY,        /* 1_3 should not get here */
  2471.   TRAMPOLINE_K_2_0,        /* 2_0 */
  2472.   TRAMPOLINE_K_2_1,        /* 2_1 */
  2473.   TRAMPOLINE_K_ARITY,        /* 2_2 should not get here */
  2474.   TRAMPOLINE_K_ARITY,        /* 2_3 should not get here */
  2475.   TRAMPOLINE_K_3_0,        /* 3_0 */
  2476.   TRAMPOLINE_K_3_1,        /* 3_1 */
  2477.   TRAMPOLINE_K_3_2,        /* 3_2 */
  2478.   TRAMPOLINE_K_ARITY,        /* 3_3 should not get here */
  2479.   TRAMPOLINE_K_4_0,        /* 4_0 */
  2480.   TRAMPOLINE_K_4_1,        /* 4_1 */
  2481.   TRAMPOLINE_K_4_2,        /* 4_2 */
  2482.   TRAMPOLINE_K_4_3        /* 4_3 */
  2483. };
  2484.  
  2485. /*
  2486.   make_uuo_link is called by C and initializes a compiled procedure
  2487.   cache at a location given by a block and an offset.
  2488.  
  2489.   make_uuo_link checks its procedure argument, and:
  2490.  
  2491.   - If it is not a compiled procedure, an entity, or a primitive
  2492.   procedure with a matching number of arguments, it stores a fake
  2493.   compiled procedure which will invoke comutil_operator_interpreted_trap
  2494.   when invoked.
  2495.  
  2496.   - If its argument is an entity, it stores a fake compiled procedure
  2497.   which will invoke comutil_operator_entity_trap when invoked.
  2498.  
  2499.   - If its argument is a primitive, it stores a fake compiled procedure
  2500.   which will invoke comutil_operator_primitive_trap, or
  2501.   comutil_operator_lexpr_trap when invoked.
  2502.  
  2503.   - If its argument is a compiled procedure that expects more or
  2504.   less arguments than those provided, it stores a fake compiled
  2505.   procedure which will invoke comutil_operator_arity_trap, or one of
  2506.   its specialized versions when invoked.
  2507.  
  2508.   - Otherwise, the actual (compatible) operator is stored.
  2509. */
  2510.  
  2511. C_UTILITY long
  2512. DEFUN (make_uuo_link,
  2513.        (procedure, extension, block, offset),
  2514.        SCHEME_OBJECT procedure AND SCHEME_OBJECT extension
  2515.        AND SCHEME_OBJECT block AND
  2516.        long offset)
  2517. {
  2518.   long kind, result, nactuals;
  2519.   SCHEME_OBJECT orig_proc, trampoline, *cache_address;
  2520.  
  2521.   cache_address = (MEMORY_LOC (block, offset));
  2522.   EXTRACT_EXECUTE_CACHE_ARITY (nactuals, cache_address);
  2523.   /* nactuals >= 0 */
  2524.  
  2525.   orig_proc = procedure;
  2526. loop:
  2527.   switch (OBJECT_TYPE (procedure))
  2528.   {
  2529.     case TC_COMPILED_ENTRY:
  2530.     {
  2531.       SCHEME_OBJECT *entry;
  2532.       long nmin, nmax;
  2533.  
  2534.       entry = (OBJECT_ADDRESS (procedure));
  2535.       nmax = (COMPILED_ENTRY_MAXIMUM_ARITY (entry));
  2536.       if (nactuals == nmax)
  2537.       {
  2538.         store_uuo_link (procedure, cache_address);
  2539.         return (PRIM_DONE);
  2540.       }
  2541.       nmin = (COMPILED_ENTRY_MINIMUM_ARITY (entry));
  2542.       if ((nmax > 1) && (nmin > 0) && (nmin <= nactuals) &&
  2543.           (nactuals <= TRAMPOLINE_TABLE_SIZE) &&
  2544.           (nmax <= (TRAMPOLINE_TABLE_SIZE + 1)))
  2545.       {
  2546.         kind = (trampoline_arity_table[((nmax - 2) * TRAMPOLINE_TABLE_SIZE) +
  2547.                        (nactuals - 1)]);
  2548.     /* Paranoia */
  2549.     if (kind != TRAMPOLINE_K_ARITY)
  2550.     {
  2551.       nactuals = 0;
  2552.       break;
  2553.     }
  2554.       }
  2555.       kind = TRAMPOLINE_K_ARITY;
  2556.       break;
  2557.     }
  2558.  
  2559.     case TC_ENTITY:
  2560.     {
  2561.       SCHEME_OBJECT data, tag, handler;
  2562.  
  2563.       data = (MEMORY_REF (procedure, ENTITY_DATA));
  2564.       if ((VECTOR_P (data))
  2565.       && (nactuals < (VECTOR_LENGTH (data)))
  2566.       && ((VECTOR_REF (data, nactuals)) != SHARP_F)
  2567.       && ((VECTOR_REF (data, 0))
  2568.           == (Get_Fixed_Obj_Slot (ARITY_DISPATCHER_TAG))))
  2569.       {
  2570.     if (procedure == orig_proc)
  2571.     {
  2572.       procedure = (VECTOR_REF (data, nactuals));
  2573.       goto loop;
  2574.     }
  2575.     else
  2576.     {
  2577.       /* No loops allowed! */
  2578.       procedure = orig_proc;
  2579.     }
  2580.       }
  2581.       kind = TRAMPOLINE_K_ENTITY;
  2582.       break;
  2583.     }
  2584.  
  2585.     case TC_PRIMITIVE:
  2586.     {
  2587.       long arity;
  2588.       extern long primitive_to_arity ();
  2589.  
  2590.       arity = primitive_to_arity (procedure);
  2591.       if (arity == (nactuals - 1))
  2592.       {
  2593.     nactuals = 0;
  2594.         kind = TRAMPOLINE_K_PRIMITIVE;
  2595.       }
  2596.       else if (arity == LEXPR_PRIMITIVE_ARITY)
  2597.       {
  2598.         kind = TRAMPOLINE_K_LEXPR_PRIMITIVE;
  2599.       }
  2600.       else
  2601.       {
  2602.         kind = TRAMPOLINE_K_OTHER;
  2603.       }
  2604.       break;
  2605.     }
  2606.  
  2607.     case TC_PROCEDURE: /* and some others... */
  2608.     default:
  2609.     uuo_link_interpreted:
  2610.     {
  2611.       kind = TRAMPOLINE_K_INTERPRETED;
  2612.       break;
  2613.     }
  2614.   }
  2615.   if (nactuals == 0)
  2616.   {
  2617.     result = (make_redirection_trampoline (&trampoline, kind, procedure));
  2618.   }
  2619.   else
  2620.   {
  2621.     result = (make_apply_trampoline (&trampoline, kind, procedure, nactuals));
  2622.   }
  2623.   if (result != PRIM_DONE)
  2624.   {
  2625.     return (result);
  2626.   }
  2627.   store_uuo_link (trampoline, cache_address);
  2628.   return (PRIM_DONE);
  2629. }
  2630.  
  2631. C_UTILITY long
  2632. DEFUN (make_fake_uuo_link,
  2633.        (extension, block, offset),
  2634.        SCHEME_OBJECT extension AND SCHEME_OBJECT block AND
  2635.        long offset)
  2636. {
  2637.   long result;
  2638.   SCHEME_OBJECT trampoline, *cache_address;
  2639.  
  2640.   result = (make_trampoline (&trampoline,
  2641.                  ((format_word) FORMAT_WORD_CMPINT),
  2642.                  TRAMPOLINE_K_LOOKUP,
  2643.                  3,
  2644.                  extension,
  2645.                  block,
  2646.                  (LONG_TO_UNSIGNED_FIXNUM (offset))));
  2647.   if (result != PRIM_DONE)
  2648.   {
  2649.     return (result);
  2650.   }
  2651.   cache_address = (MEMORY_LOC (block, offset));
  2652.   store_uuo_link (trampoline, cache_address);
  2653.   return (PRIM_DONE);
  2654. }
  2655.  
  2656. /* C_UTILITY long fake_uuo_link_p does not appear to be used anymore */
  2657.  
  2658. C_UTILITY long
  2659. DEFUN (coerce_to_compiled,
  2660.        (procedure, arity, location),
  2661.        SCHEME_OBJECT procedure AND long arity AND SCHEME_OBJECT *location)
  2662. {
  2663.   long frame_size;
  2664.  
  2665.   frame_size = (arity + 1);
  2666.   if ((!(COMPILED_CODE_ADDRESS_P (procedure))) ||
  2667.       ((COMPILED_ENTRY_MAXIMUM_ARITY (OBJECT_ADDRESS (procedure))) !=
  2668.        frame_size))
  2669.   {
  2670.     if (frame_size > FORMAT_BYTE_FRAMEMAX)
  2671.     {
  2672.       return (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  2673.     }
  2674.     return (make_trampoline (location,
  2675.                  ((format_word)
  2676.                   (MAKE_FORMAT_WORD (frame_size, frame_size))),
  2677.                  TRAMPOLINE_K_APPLY,
  2678.                  2,
  2679.                  procedure,
  2680.                  (LONG_TO_UNSIGNED_FIXNUM (frame_size)),
  2681.                  SHARP_F));
  2682.   }
  2683.   (*location) = procedure;
  2684.   return (PRIM_DONE);
  2685. }
  2686.  
  2687. /* Initialization */
  2688.  
  2689. #define COMPILER_INTERFACE_VERSION        3
  2690.  
  2691. #ifndef COMPILER_REGBLOCK_N_FIXED
  2692. #  define COMPILER_REGBLOCK_N_FIXED        16
  2693. #endif
  2694.  
  2695. #ifndef COMPILER_REGBLOCK_N_TEMPS
  2696. #  define COMPILER_REGBLOCK_N_TEMPS        256
  2697. #endif
  2698.  
  2699. #ifndef COMPILER_REGBLOCK_EXTRA_SIZE
  2700. #  define COMPILER_REGBLOCK_EXTRA_SIZE        0
  2701. #endif
  2702.  
  2703. #if (REGBLOCK_MINIMUM_LENGTH > COMPILER_REGBLOCK_N_FIXED)
  2704. #  include "ERROR: cmpint.c and const.h disagree on REGBLOCK_MINIMUM_LENGTH!"
  2705. #endif
  2706.  
  2707. /* ((sizeof(SCHEME_OBJECT)) / (sizeof(SCHEME_OBJECT))) */
  2708.  
  2709. #define COMPILER_FIXED_SIZE    1
  2710.  
  2711. #ifndef COMPILER_TEMP_SIZE
  2712. #  define COMPILER_TEMP_SIZE    ((sizeof (double)) / (sizeof (SCHEME_OBJECT)))
  2713. #endif
  2714.  
  2715. #define REGBLOCK_LENGTH                            \
  2716.   ((COMPILER_REGBLOCK_N_FIXED * COMPILER_FIXED_SIZE) +            \
  2717.    (COMPILER_REGBLOCK_N_TEMPS * COMPILER_TEMP_SIZE) +            \
  2718.    COMPILER_REGBLOCK_EXTRA_SIZE)
  2719.  
  2720. #ifndef ASM_RESET_HOOK
  2721. #  define ASM_RESET_HOOK() NOP()
  2722. #endif
  2723.  
  2724. long
  2725.   compiler_processor_type,
  2726.   compiler_interface_version;
  2727.  
  2728. SCHEME_OBJECT
  2729.   compiler_utilities,
  2730.   return_to_interpreter;
  2731.  
  2732. #ifndef REGBLOCK_ALLOCATED_BY_INTERFACE
  2733. SCHEME_OBJECT
  2734.   Registers[REGBLOCK_LENGTH];
  2735. #endif
  2736.  
  2737. static void
  2738. DEFUN_VOID (compiler_reset_internal)
  2739. {
  2740.   /* Other stuff can be placed here. */
  2741.  
  2742.   Registers[REGBLOCK_CLOSURE_FREE] = ((SCHEME_OBJECT) NULL);
  2743.   Registers[REGBLOCK_CLOSURE_SPACE] = ((SCHEME_OBJECT) 0);
  2744.  
  2745.   ASM_RESET_HOOK();
  2746.  
  2747.   return_to_interpreter =
  2748.     (ENTRY_TO_OBJECT (TRAMPOLINE_ENTRY_POINT
  2749.               (OBJECT_ADDRESS (compiler_utilities))));
  2750.  
  2751.   return;
  2752. }
  2753.  
  2754. C_UTILITY void
  2755. DEFUN (compiler_reset,
  2756.        (new_block),
  2757.        SCHEME_OBJECT new_block)
  2758. {
  2759.   /* Called after a disk restore */
  2760.  
  2761.   if ((OBJECT_TYPE (new_block)) != TC_COMPILED_CODE_BLOCK)
  2762.   {
  2763.     extern void compiler_reset_error ();
  2764.  
  2765.     compiler_reset_error ();
  2766.   }
  2767.   else
  2768.   {
  2769.     compiler_utilities = new_block;
  2770.     compiler_reset_internal ();
  2771.   }
  2772.   return;
  2773. }
  2774.  
  2775. C_UTILITY void
  2776. DEFUN (compiler_initialize,
  2777.        (fasl_p),
  2778.        long fasl_p)
  2779. {
  2780.   /* Start-up of whole interpreter */
  2781.  
  2782.   long code;
  2783.   SCHEME_OBJECT trampoline, *block;
  2784.  
  2785.   compiler_processor_type = COMPILER_PROCESSOR_TYPE;
  2786.   compiler_interface_version = COMPILER_INTERFACE_VERSION;
  2787.   if (fasl_p)
  2788.   {
  2789.     extern SCHEME_OBJECT *copy_to_constant_space();
  2790.  
  2791.     code = (make_trampoline (&trampoline,
  2792.                  ((format_word) FORMAT_WORD_RETURN),
  2793.                  TRAMPOLINE_K_RETURN,
  2794.                  0, SHARP_F, SHARP_F, SHARP_F));
  2795.     if (code != PRIM_DONE)
  2796.     {
  2797.       fprintf (stderr,
  2798.            "compiler_initialize: Not enough space!\n");
  2799.       Microcode_Termination (TERM_NO_SPACE);
  2800.     }
  2801.     block = (compiled_entry_to_block_address (trampoline));
  2802.     block = (copy_to_constant_space (block, (1 + (OBJECT_DATUM (block[0])))));
  2803.     compiler_utilities = (MAKE_CC_BLOCK (block));
  2804.     compiler_reset_internal ();
  2805.   }
  2806.   else
  2807.   {
  2808.     /* Delay until after band-load, when compiler_reset will be invoked. */
  2809.     compiler_utilities = SHARP_F;
  2810.     return_to_interpreter = SHARP_F;
  2811. #ifdef sonyrisc
  2812.     /* On the Sony NEWS 3250, this procedure initializes the
  2813.        floating-point CPU control register to enable the IEEE traps.
  2814.        This is normally executed by `compiler_reset' from LOAD-BAND,
  2815.        but the Sony operating system saves the control register in
  2816.        `setjmp' and restores it on `longjmp', so we must initialize
  2817.        the register before `setjmp' is called.  */
  2818.     interface_initialize ();
  2819. #endif
  2820.   }
  2821.   return;
  2822. }
  2823.  
  2824. #else    /* not HAS_COMPILER_SUPPORT */
  2825.  
  2826. /* Stubs for compiler utilities.
  2827.    All entries error out or kill the microcode.
  2828.  */
  2829.  
  2830. #include "ansidecl.h"    /* Macros to support ANSI declarations */
  2831. #include "config.h"    /* Machine configurations */
  2832. #include "object.h"    /* Making pointers */
  2833. #include "sdata.h"    /* Needed by const.h */
  2834. #include "types.h"    /* Needed by const.h */
  2835. #include "errors.h"    /* Error codes and Termination codes */
  2836. #include "const.h"    /* REGBLOCK_MINIMUM_LENGTH */
  2837. #include "returns.h"    /* RC_POP_FROM_COMPILED_CODE */
  2838.  
  2839. extern void EXFUN (Microcode_Termination, (int code));
  2840. extern void EXFUN (compiler_reset_error, (void));
  2841.  
  2842. extern long
  2843.   compiler_interface_version,
  2844.   compiler_processor_type;
  2845.  
  2846. extern SCHEME_OBJECT
  2847.   Registers[],
  2848.   compiler_utilities,
  2849.   return_to_interpreter;
  2850.  
  2851. extern long
  2852.   EXFUN (enter_compiled_expression, (void)),
  2853.   EXFUN (apply_compiled_procedure, (void)),
  2854.   EXFUN (return_to_compiled_code, (void)),
  2855.   EXFUN (make_fake_uuo_link,
  2856.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  2857.   EXFUN (make_uuo_link,
  2858.      (SCHEME_OBJECT value, SCHEME_OBJECT extension,
  2859.       SCHEME_OBJECT block, long offset)),
  2860.   EXFUN (compiled_block_closure_p, (SCHEME_OBJECT block)),
  2861.   EXFUN (compiled_entry_closure_p, (SCHEME_OBJECT entry)),
  2862.   EXFUN (compiled_entry_to_block_offset, (SCHEME_OBJECT entry)),
  2863.   EXFUN (coerce_to_compiled,
  2864.      (SCHEME_OBJECT object, long arity, SCHEME_OBJECT *location));
  2865.  
  2866. extern SCHEME_OBJECT
  2867.   EXFUN (extract_uuo_link, (SCHEME_OBJECT block, long offset)),
  2868.   EXFUN (extract_variable_cache,
  2869.      (SCHEME_OBJECT extension, long offset)),
  2870.   EXFUN (compiled_block_debugging_info, (SCHEME_OBJECT block)),
  2871.   EXFUN (compiled_block_environment, (SCHEME_OBJECT block)),
  2872.   EXFUN (compiled_closure_to_entry, (SCHEME_OBJECT entry)),
  2873.   * EXFUN (compiled_entry_to_block_address, (SCHEME_OBJECT entry)),
  2874.   EXFUN (compiled_entry_to_block, (SCHEME_OBJECT entry));
  2875.  
  2876. extern void
  2877.   EXFUN (compiler_reset, (SCHEME_OBJECT new_block)),
  2878.   EXFUN (compiler_initialize, (long fasl_p)),
  2879.   EXFUN (store_variable_cache,
  2880.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  2881.   EXFUN (compiled_entry_type,
  2882.      (SCHEME_OBJECT entry, long *buffer));
  2883.  
  2884. SCHEME_OBJECT
  2885.   Registers[REGBLOCK_MINIMUM_LENGTH],
  2886.   compiler_utilities,
  2887.   return_to_interpreter;
  2888.  
  2889. long
  2890.   compiler_interface_version,
  2891.   compiler_processor_type;
  2892.  
  2893. long
  2894. DEFUN_VOID (enter_compiled_expression)
  2895. {
  2896.   return (ERR_EXECUTE_MANIFEST_VECTOR);
  2897. }
  2898.  
  2899. long
  2900. DEFUN_VOID (apply_compiled_procedure)
  2901. {
  2902.   return (ERR_INAPPLICABLE_OBJECT);
  2903. }
  2904.  
  2905. long
  2906. DEFUN_VOID (return_to_compiled_code)
  2907. {
  2908.   return (ERR_INAPPLICABLE_CONTINUATION);
  2909. }
  2910.  
  2911. /* Bad entry points. */
  2912.  
  2913. long
  2914. DEFUN (make_fake_uuo_link,
  2915.        (extension, block, offset),
  2916.        SCHEME_OBJECT extension AND SCHEME_OBJECT block AND
  2917.        long offset)
  2918. {
  2919.   Microcode_Termination (TERM_COMPILER_DEATH);
  2920.   /*NOTREACHED*/
  2921. }
  2922.  
  2923. long
  2924. DEFUN (make_uuo_link,
  2925.        (value, extension, block, offset),
  2926.        SCHEME_OBJECT value AND SCHEME_OBJECT extension AND
  2927.        SCHEME_OBJECT block AND long offset)
  2928. {
  2929.   Microcode_Termination (TERM_COMPILER_DEATH);
  2930.   /*NOTREACHED*/
  2931. }
  2932.  
  2933. SCHEME_OBJECT
  2934. DEFUN (extract_uuo_link,
  2935.        (block, offset),
  2936.        SCHEME_OBJECT block AND long offset)
  2937. {
  2938.   Microcode_Termination (TERM_COMPILER_DEATH);
  2939.   /*NOTREACHED*/
  2940. }
  2941.  
  2942. void
  2943. DEFUN (store_variable_cache,
  2944.        (extension, block, offset),
  2945.        SCHEME_OBJECT extension AND SCHEME_OBJECT block AND
  2946.        long offset)
  2947. {
  2948.   Microcode_Termination (TERM_COMPILER_DEATH);
  2949.   /*NOTREACHED*/
  2950. }
  2951.  
  2952. SCHEME_OBJECT
  2953. DEFUN (extract_variable_cache,
  2954.        (block, offset),
  2955.        SCHEME_OBJECT block AND
  2956.        long offset)
  2957. {
  2958.   Microcode_Termination (TERM_COMPILER_DEATH);
  2959.   /*NOTREACHED*/
  2960. }
  2961.  
  2962. SCHEME_OBJECT
  2963. DEFUN (compiled_block_debugging_info,
  2964.        (block),
  2965.        SCHEME_OBJECT block)
  2966. {
  2967.   Microcode_Termination (TERM_COMPILER_DEATH);
  2968.   /*NOTREACHED*/
  2969. }
  2970.  
  2971. SCHEME_OBJECT
  2972. DEFUN (compiled_block_environment,
  2973.        (block),
  2974.        SCHEME_OBJECT block)
  2975. {
  2976.   Microcode_Termination (TERM_COMPILER_DEATH);
  2977.   /*NOTREACHED*/
  2978. }
  2979.  
  2980. long
  2981. DEFUN (compiled_block_closure_p,
  2982.        (block),
  2983.        SCHEME_OBJECT block)
  2984. {
  2985.   Microcode_Termination (TERM_COMPILER_DEATH);
  2986.   /*NOTREACHED*/
  2987. }
  2988.  
  2989. SCHEME_OBJECT *
  2990. DEFUN (compiled_entry_to_block_address,
  2991.        (entry),
  2992.        SCHEME_OBJECT entry)
  2993. {
  2994.   Microcode_Termination (TERM_COMPILER_DEATH);
  2995.   /*NOTREACHED*/
  2996. }
  2997.  
  2998. long
  2999. DEFUN (compiled_entry_to_block_offset,
  3000.        (entry),
  3001.        SCHEME_OBJECT entry)
  3002. {
  3003.   Microcode_Termination (TERM_COMPILER_DEATH);
  3004.   /*NOTREACHED*/
  3005. }
  3006.  
  3007. SCHEME_OBJECT
  3008. DEFUN (compiled_entry_to_block,
  3009.        (entry),
  3010.        SCHEME_OBJECT entry)
  3011. {
  3012.   Microcode_Termination (TERM_COMPILER_DEATH);
  3013.   /*NOTREACHED*/
  3014. }
  3015.  
  3016.  
  3017. void
  3018. DEFUN (compiled_entry_type,
  3019.        (entry, buffer),
  3020.        SCHEME_OBJECT entry AND long *buffer)
  3021. {
  3022.   Microcode_Termination (TERM_COMPILER_DEATH);
  3023.   /*NOTREACHED*/
  3024. }
  3025.  
  3026. long
  3027. DEFUN (compiled_entry_closure_p,
  3028.        (entry),
  3029.        SCHEME_OBJECT entry)
  3030. {
  3031.   Microcode_Termination (TERM_COMPILER_DEATH);
  3032.   /*NOTREACHED*/
  3033. }
  3034.  
  3035. SCHEME_OBJECT
  3036. DEFUN (compiled_closure_to_entry,
  3037.        (entry),
  3038.        SCHEME_OBJECT entry)
  3039. {
  3040.   Microcode_Termination (TERM_COMPILER_DEATH);
  3041.   /*NOTREACHED*/
  3042. }
  3043.  
  3044. #define LOSING_RETURN_ADDRESS(name)                    \
  3045. extern long EXFUN (name, (void));                    \
  3046. long                                    \
  3047. DEFUN_VOID (name)                            \
  3048. {                                    \
  3049.   Microcode_Termination (TERM_COMPILER_DEATH);                \
  3050.   /*NOTREACHED*/                            \
  3051. }
  3052.  
  3053. LOSING_RETURN_ADDRESS (comp_interrupt_restart)
  3054. LOSING_RETURN_ADDRESS (comp_lookup_apply_restart)
  3055. LOSING_RETURN_ADDRESS (comp_reference_restart)
  3056. LOSING_RETURN_ADDRESS (comp_access_restart)
  3057. LOSING_RETURN_ADDRESS (comp_unassigned_p_restart)
  3058. LOSING_RETURN_ADDRESS (comp_unbound_p_restart)
  3059. LOSING_RETURN_ADDRESS (comp_assignment_restart)
  3060. LOSING_RETURN_ADDRESS (comp_definition_restart)
  3061. LOSING_RETURN_ADDRESS (comp_safe_reference_restart)
  3062. LOSING_RETURN_ADDRESS (comp_lookup_trap_restart)
  3063. LOSING_RETURN_ADDRESS (comp_assignment_trap_restart)
  3064. LOSING_RETURN_ADDRESS (comp_op_lookup_trap_restart)
  3065. LOSING_RETURN_ADDRESS (comp_cache_lookup_apply_restart)
  3066. LOSING_RETURN_ADDRESS (comp_safe_lookup_trap_restart)
  3067. LOSING_RETURN_ADDRESS (comp_unassigned_p_trap_restart)
  3068. LOSING_RETURN_ADDRESS (comp_link_caches_restart)
  3069. LOSING_RETURN_ADDRESS (comp_error_restart)
  3070.  
  3071. /* NOP entry points */
  3072.  
  3073. void
  3074. DEFUN (compiler_reset,
  3075.        (new_block),
  3076.        SCHEME_OBJECT new_block)
  3077. {
  3078.   extern void compiler_reset_error();
  3079.  
  3080.   if (new_block != SHARP_F)
  3081.   {
  3082.     compiler_reset_error();
  3083.   }
  3084.   return;
  3085. }
  3086.  
  3087. void
  3088. DEFUN (compiler_initialize,
  3089.        (fasl_p),
  3090.        long fasl_p)
  3091. {
  3092.   compiler_processor_type = 0;
  3093.   compiler_interface_version = 0;
  3094.   compiler_utilities = SHARP_F;
  3095.   return_to_interpreter =
  3096.     (MAKE_OBJECT (TC_RETURN_CODE, RC_POP_FROM_COMPILED_CODE));
  3097.   return;
  3098. }
  3099.  
  3100. /* Identity procedure */
  3101.  
  3102. long
  3103. DEFUN (coerce_to_compiled,
  3104.        (object, arity, location),
  3105.        SCHEME_OBJECT object AND long arity AND SCHEME_OBJECT *location)
  3106. {
  3107.   *location = object;
  3108.   return (PRIM_DONE);
  3109. }
  3110.  
  3111. #endif    /* HAS_COMPILER_SUPPORT */
  3112.